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