org/sonews/mlgw/Dispatcher.java
author chris <chris@marvin>
Thu, 06 Aug 2009 18:34:10 +0200
changeset 5 ad210aa137a4
parent 3 2fdc9cc89502
child 12 bb6990c0dd1a
permissions -rw-r--r--
Removing tags as they point to invalid changesets after history refactoring.
chris@1
     1
/*
chris@1
     2
 *   SONEWS News Server
chris@1
     3
 *   see AUTHORS for the list of contributors
chris@1
     4
 *
chris@1
     5
 *   This program is free software: you can redistribute it and/or modify
chris@1
     6
 *   it under the terms of the GNU General Public License as published by
chris@1
     7
 *   the Free Software Foundation, either version 3 of the License, or
chris@1
     8
 *   (at your option) any later version.
chris@1
     9
 *
chris@1
    10
 *   This program is distributed in the hope that it will be useful,
chris@1
    11
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
chris@1
    12
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
chris@1
    13
 *   GNU General Public License for more details.
chris@1
    14
 *
chris@1
    15
 *   You should have received a copy of the GNU General Public License
chris@1
    16
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
chris@1
    17
 */
chris@1
    18
chris@1
    19
package org.sonews.mlgw;
chris@1
    20
chris@1
    21
import java.io.IOException;
chris@1
    22
import java.util.ArrayList;
chris@1
    23
import java.util.List;
chris@1
    24
import javax.mail.Address;
chris@1
    25
import javax.mail.Authenticator;
chris@1
    26
import javax.mail.Message;
chris@1
    27
import javax.mail.MessagingException;
chris@1
    28
import javax.mail.PasswordAuthentication;
chris@1
    29
import javax.mail.internet.InternetAddress;
chris@3
    30
import org.sonews.config.Config;
chris@3
    31
import org.sonews.storage.Article;
chris@3
    32
import org.sonews.storage.Headers;
chris@3
    33
import org.sonews.storage.StorageBackendException;
chris@3
    34
import org.sonews.storage.StorageManager;
chris@1
    35
import org.sonews.util.Log;
chris@1
    36
import org.sonews.util.Stats;
chris@1
    37
chris@1
    38
/**
chris@1
    39
 * Dispatches messages from mailing list or newsserver or vice versa.
chris@1
    40
 * @author Christian Lins
chris@1
    41
 * @since sonews/0.5.0
chris@1
    42
 */
chris@1
    43
public class Dispatcher 
chris@1
    44
{
chris@1
    45
chris@1
    46
  static class PasswordAuthenticator extends Authenticator
chris@1
    47
  {
chris@1
    48
    
chris@1
    49
    @Override
chris@1
    50
    public PasswordAuthentication getPasswordAuthentication()
chris@1
    51
    {
chris@1
    52
      final String username = 
chris@3
    53
        Config.inst().get(Config.MLSEND_USER, "user");
chris@1
    54
      final String password = 
chris@3
    55
        Config.inst().get(Config.MLSEND_PASSWORD, "mysecret");
chris@1
    56
chris@1
    57
      return new PasswordAuthentication(username, password);
chris@1
    58
    }
chris@1
    59
    
chris@1
    60
  }
chris@1
    61
  
chris@1
    62
  /**
chris@1
    63
   * Posts a message that was received from a mailing list to the 
chris@1
    64
   * appropriate newsgroup.
chris@1
    65
   * @param msg
chris@1
    66
   */
chris@1
    67
  public static boolean toGroup(final Message msg)
chris@1
    68
  {
chris@1
    69
    try
chris@1
    70
    {
chris@1
    71
      Address[] to = msg.getAllRecipients(); // includes TO/CC/BCC
chris@1
    72
      if(to == null || to.length <= 0)
chris@1
    73
      {
chris@3
    74
        to = msg.getReplyTo();
chris@3
    75
      }
chris@3
    76
chris@3
    77
      if(to == null || to.length <= 0)
chris@3
    78
      {
chris@3
    79
        Log.msg("Skipping message because no recipient!", false);
chris@1
    80
        return false;
chris@1
    81
      }
chris@1
    82
      else
chris@1
    83
      {
chris@3
    84
        boolean      posted     = false;
chris@3
    85
        List<String> newsgroups = new ArrayList<String>();
chris@3
    86
chris@3
    87
        for (Address toa : to) // Address can have '<' '>' around
chris@1
    88
        {
chris@3
    89
          if (toa instanceof InternetAddress)
chris@1
    90
          {
chris@3
    91
            List<String> groups = StorageManager.current()
chris@3
    92
              .getGroupsForList((InternetAddress)toa);
chris@3
    93
            newsgroups.addAll(groups);
chris@1
    94
          }
chris@3
    95
        }
chris@3
    96
chris@3
    97
        if (newsgroups.size() > 0)
chris@3
    98
        {
chris@3
    99
          StringBuilder groups = new StringBuilder();
chris@3
   100
          for(int n = 0; n < newsgroups.size(); n++)
chris@1
   101
          {
chris@3
   102
            groups.append(newsgroups.get(n));
chris@3
   103
            if(n + 1 != newsgroups.size())
chris@3
   104
            {
chris@3
   105
              groups.append(',');
chris@3
   106
            }
chris@3
   107
          }
chris@3
   108
          Log.msg("Posting to group " + groups.toString(), true);
chris@1
   109
chris@3
   110
          // Create new Article object
chris@3
   111
          Article article = new Article(msg);
chris@3
   112
          article.setGroup(groups.toString());
chris@3
   113
          article.removeHeader(Headers.REPLY_TO);
chris@3
   114
          article.removeHeader(Headers.TO);
chris@3
   115
chris@3
   116
          // Write article to database
chris@3
   117
          if(!StorageManager.current().isArticleExisting(article.getMessageID()))
chris@3
   118
          {
chris@3
   119
            StorageManager.current().addArticle(article);
chris@3
   120
            Stats.getInstance().mailGatewayed(
chris@3
   121
              article.getHeader(Headers.NEWSGROUPS)[0]);
chris@1
   122
          }
chris@1
   123
          else
chris@1
   124
          {
chris@3
   125
            Log.msg("Article " + article.getMessageID() + " already existing.", true);
chris@1
   126
          }
chris@3
   127
          posted = true;
chris@3
   128
        }
chris@3
   129
        else
chris@3
   130
        {
chris@3
   131
          StringBuilder buf = new StringBuilder();
chris@3
   132
          for(Address toa : to)
chris@3
   133
          {
chris@3
   134
            buf.append(' ');
chris@3
   135
            buf.append(toa.toString());
chris@3
   136
          }
chris@3
   137
          Log.msg("No group for" + buf.toString(), false);
chris@3
   138
        }
chris@1
   139
        return posted;
chris@1
   140
      }
chris@1
   141
    }
chris@1
   142
    catch(Exception ex)
chris@1
   143
    {
chris@1
   144
      ex.printStackTrace();
chris@1
   145
      return false;
chris@1
   146
    }
chris@1
   147
  }
chris@1
   148
  
chris@1
   149
  /**
chris@1
   150
   * Mails a message received through NNTP to the appropriate mailing list.
chris@1
   151
   */
chris@1
   152
  public static void toList(Article article)
chris@3
   153
    throws IOException, MessagingException, StorageBackendException
chris@1
   154
  {
chris@1
   155
    // Get mailing lists for the group of this article
chris@1
   156
    List<String> listAddresses = new ArrayList<String>();
chris@1
   157
    String[]     groupnames    = article.getHeader(Headers.NEWSGROUPS)[0].split(",");
chris@1
   158
    
chris@1
   159
    for(String groupname : groupnames)
chris@1
   160
    {
chris@3
   161
      String listAddress = StorageManager.current().getListForGroup(groupname);
chris@1
   162
      if(listAddress != null)
chris@1
   163
      {
chris@1
   164
        listAddresses.add(listAddress);
chris@1
   165
      }
chris@1
   166
    }
chris@1
   167
chris@1
   168
    for(String listAddress : listAddresses)
chris@1
   169
    {
chris@1
   170
      // Compose message and send it via given SMTP-Host
chris@3
   171
      String smtpHost = Config.inst().get(Config.MLSEND_HOST, "localhost");
chris@3
   172
      int    smtpPort = Config.inst().get(Config.MLSEND_PORT, 25);
chris@3
   173
      String smtpUser = Config.inst().get(Config.MLSEND_USER, "user");
chris@3
   174
      String smtpPw   = Config.inst().get(Config.MLSEND_PASSWORD, "mysecret");
chris@3
   175
      String smtpFrom = Config.inst().get(
chris@3
   176
          Config.MLSEND_ADDRESS, article.getHeader(Headers.FROM)[0]);
chris@1
   177
chris@3
   178
      // TODO: Make Article cloneable()
chris@3
   179
      String group = article.getHeader(Headers.NEWSGROUPS)[0];
chris@3
   180
      article.getMessageID(); // Make sure an ID is existing
chris@3
   181
      article.removeHeader(Headers.NEWSGROUPS);
chris@3
   182
      article.removeHeader(Headers.PATH);
chris@3
   183
      article.removeHeader(Headers.LINES);
chris@3
   184
      article.removeHeader(Headers.BYTES);
chris@1
   185
chris@3
   186
      article.setHeader("To", listAddress);
chris@3
   187
      article.setHeader("Reply-To", listAddress);
chris@1
   188
chris@3
   189
      if(Config.inst().get(Config.MLSEND_RW_SENDER, false))
chris@1
   190
      {
chris@3
   191
        rewriteSenderAddress(article); // Set the SENDER address
chris@1
   192
      }
chris@1
   193
chris@3
   194
      SMTPTransport smtpTransport = new SMTPTransport(smtpHost, smtpPort);
chris@3
   195
      smtpTransport.send(article, smtpFrom, listAddress);
chris@3
   196
      smtpTransport.close();
chris@1
   197
chris@3
   198
      Stats.getInstance().mailGatewayed(group);
chris@1
   199
      Log.msg("MLGateway: Mail " + article.getHeader("Subject")[0] 
chris@1
   200
        + " was delivered to " + listAddress + ".", true);
chris@1
   201
    }
chris@1
   202
  }
chris@1
   203
  
chris@1
   204
  /**
chris@1
   205
   * Sets the SENDER header of the given MimeMessage. This might be necessary
chris@1
   206
   * for moderated groups that does not allow the "normal" FROM sender.
chris@1
   207
   * @param msg
chris@1
   208
   * @throws javax.mail.MessagingException
chris@1
   209
   */
chris@3
   210
  private static void rewriteSenderAddress(Article msg)
chris@1
   211
    throws MessagingException
chris@1
   212
  {
chris@3
   213
    String mlAddress = Config.inst().get(Config.MLSEND_ADDRESS, null);
chris@1
   214
chris@1
   215
    if(mlAddress != null)
chris@1
   216
    {
chris@3
   217
      msg.setHeader(Headers.SENDER, mlAddress);
chris@1
   218
    }
chris@1
   219
    else
chris@1
   220
    {
chris@1
   221
      throw new MessagingException("Cannot rewrite SENDER header!");
chris@1
   222
    }
chris@1
   223
  }
chris@1
   224
  
chris@1
   225
}