I apologize if I overlooked some hidden feature, but I would really like to use something like that:

Let's say I have 3 different taxonomy tags for pulling the content of nodes into the newsletter...
1. news
2. education
3. useful links

In the template I would prefer to organize these entries in sort of groups (with headings), like


Useful links

However I can't figure out how to do this with the [repeat] ... [/repeat] tokens.
The order of nodes in the newsletter is always by creation time of content.

Are there any other helper modules available to accomplish the task?
Or do I have to fiddle with the SQL SELECT clause that pulls the nodes from the DB?


I've managed to change the SQL, so the return order is not sorted just by time of creation of content, but instead gives priority to
the taxonomy tag & weight.

Here's the modified code:

   * Builds a dynamic query
   * that gets the current nodes to be sent with the current newsletter.
  protected function getQuery() {
    $tids = newsletter_get_template_terms($this->template->ntid);
    $tids = array_keys($tids) ? array_keys($tids) : array(0);

    $query = db_select('taxonomy_index', 'tax');
    $query->fields('tax', array('nid'));
    $query->join('newsletter_list', 'list', 'list.nlid = ' . (int) $this->list->nlid);
    $query->join('node', 'node', 'tax.nid = node.nid');
    $query->join('taxonomy_term_data', 'ttd', 'tax.tid = ttd.tid');
    $query->addField('node', 'created', 'created');
    $query->condition('tax.tid', $tids, 'IN');
    $query->where('(list.last_sent <= node.created) OR (list.last_sent IS NULL )');
    if (!$this->manualSendRate && !$this->customSendRate) {
      $query->where('list.send_again = CURDATE() OR list.send_again IS NULL');
    if ($this->customSendRate) {
      $query->range(0, (int) $this->list->send_rate);
    else {
      $query->range(0, (int) variable_get('newsletter_node_limit', 50));
    $query->orderBy('ttd.weight', 'ASC');
    $query->orderBy('created', 'DESC');

    return $query;


ParisLiakos’s picture

Hmm adding an alter hook there would be a smart thing to do.
This would be fairly easy.
Something like

drupal_alter('newsletter_node_query', $query);

or, even better a tag

Then anyone could overwrite it, without hacking the module

kutulu’s picture

Agreed. Especially when upgrading the module, those hooks & tags should be simpler.

Can you give me a hint on how to separate the content in the email?
Now the nodes are sorted, but there's no spacing between them - i would like to add a heading to each topic/taxonomy group.
Like a picture or maybe only a


The whole output should be in a table, which i've already done in the template, but as said i would like to insert topic headers inbetween the listed nodes.

I've also had problems with links appearing relative, even if i set the base_url in the settings. Even when inserting tokens with

That's why i wrote an override and extra check for links without the base_url in it.

   * Add the source and nnid to newsletter URLs so we can gather clicks.
  public function addNewsletterUrlQuery($message) {
    if (isset($message['params']['newsletter']->nnid)) {
      //global $base_url;
<strong>      $base_url = 'http://www.example.com';</strong>
      $nnid = $message['params']['newsletter']->nnid;

      $dom = new DomDocument;
      // Convert to html entities to avoid text scrumbling
      // due to encoding especially for non-latin characters.
      $message['body'] = mb_convert_encoding($message['body'], 'HTML-ENTITIES', 'UTF-8');

      $links = $dom->getElementsByTagName('a');

      foreach ($links as $link) {
        $href = $link->getAttribute('href');
        if (strpos($href, $base_url) !== FALSE) {
          $href = drupal_parse_url($href);
          $query = array_merge($href['query'], array('source' => 'newsletter', 'nnid' => $nnid));
  $link->setAttribute('href', url($href['path'], array('query' => $query)));

<strong> if (strpos($link->getAttribute('href'), $base_url) === FALSE) {         
$link->setAttribute('href', $base_url.url($href['path'], array('query' => $query)));

      // Converts back from hmtl entities
      return decode_entities($dom->saveHTML());
    return $message['body'];

I guess this is the part of code i have to alter, to achieve my goal of inserting topics...

kutulu’s picture

Issue summary:View changes

I tried to alter a few lines of code to achieve my goal of grouping content. Filename newsletter.automated.inc.