org/sonews/mlgw/Dispatcher.java
author chris <chris@marvin>
Fri Jun 26 16:48:50 2009 +0200 (2009-06-26)
changeset 1 6fceb66e1ad7
child 3 2fdc9cc89502
permissions -rw-r--r--
Hooray... sonews/0.5.0 final

HG: Enter commit message. Lines beginning with 'HG:' are removed.
HG: Remove all lines to abort the collapse operation.
     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 org.sonews.daemon.Config;
    23 import org.sonews.daemon.storage.Article;
    24 import org.sonews.util.io.ArticleInputStream;
    25 import org.sonews.daemon.storage.Database;
    26 import java.sql.SQLException;
    27 import java.util.ArrayList;
    28 import java.util.List;
    29 import java.util.Properties;
    30 import javax.mail.Address;
    31 import javax.mail.Authenticator;
    32 import javax.mail.Message;
    33 import javax.mail.MessagingException;
    34 import javax.mail.PasswordAuthentication;
    35 import javax.mail.Session;
    36 import javax.mail.Transport;
    37 import javax.mail.internet.InternetAddress;
    38 import javax.mail.internet.MimeMessage;
    39 import org.sonews.daemon.storage.Headers;
    40 import org.sonews.util.Log;
    41 import org.sonews.util.Stats;
    42 
    43 /**
    44  * Dispatches messages from mailing list or newsserver or vice versa.
    45  * @author Christian Lins
    46  * @since sonews/0.5.0
    47  */
    48 public class Dispatcher 
    49 {
    50 
    51   static class PasswordAuthenticator extends Authenticator
    52   {
    53     
    54     @Override
    55     public PasswordAuthentication getPasswordAuthentication()
    56     {
    57       final String username = 
    58         Config.getInstance().get(Config.MLSEND_USER, "user");
    59       final String password = 
    60         Config.getInstance().get(Config.MLSEND_PASSWORD, "mysecret");
    61 
    62       return new PasswordAuthentication(username, password);
    63     }
    64     
    65   }
    66   
    67   /**
    68    * Posts a message that was received from a mailing list to the 
    69    * appropriate newsgroup.
    70    * @param msg
    71    */
    72   public static boolean toGroup(final Message msg)
    73   {
    74     try
    75     {
    76       Address[] to = msg.getAllRecipients(); // includes TO/CC/BCC
    77       if(to == null || to.length <= 0)
    78       {
    79         Log.msg("Skipping message because no receipient!", true);
    80         return false;
    81       }
    82       else
    83       {
    84         boolean posted = false;
    85         for(Address toa : to) // Address can have '<' '>' around
    86         {
    87           if(!(toa instanceof InternetAddress))
    88           {
    89             continue;
    90           }
    91           String group = Database.getInstance()
    92             .getGroupForList((InternetAddress)toa);
    93           if(group != null)
    94           {
    95             Log.msg("Posting to group " + group, true);
    96 
    97             // Create new Article object
    98             Article article = new Article(msg);
    99             article.setGroup(group);
   100             
   101             // Write article to database
   102             if(!Database.getInstance().isArticleExisting(article.getMessageID()))
   103             {
   104               Database.getInstance().addArticle(article);
   105               Stats.getInstance().mailGatewayed(
   106                 article.getHeader(Headers.NEWSGROUPS)[0]);
   107             }
   108             else
   109             {
   110               Log.msg("Article " + article.getMessageID() + " already existing.", true);
   111               // TODO: It may be possible that a ML mail is posted to several
   112               // ML addresses...
   113             }
   114             posted = true;
   115           }
   116           else
   117           {
   118             Log.msg("No group for " + toa, true);
   119           }
   120         } // end for
   121         return posted;
   122       }
   123     }
   124     catch(Exception ex)
   125     {
   126       ex.printStackTrace();
   127       return false;
   128     }
   129   }
   130   
   131   /**
   132    * Mails a message received through NNTP to the appropriate mailing list.
   133    */
   134   public static void toList(Article article)
   135     throws IOException, MessagingException, SQLException
   136   {
   137     // Get mailing lists for the group of this article
   138     List<String> listAddresses = new ArrayList<String>();
   139     String[]     groupnames    = article.getHeader(Headers.NEWSGROUPS)[0].split(",");
   140     
   141     for(String groupname : groupnames)
   142     {
   143       String listAddress = Database.getInstance().getListForGroup(groupname);
   144       if(listAddress != null)
   145       {
   146         listAddresses.add(listAddress);
   147       }
   148     }
   149 
   150     for(String listAddress : listAddresses)
   151     {
   152       // Compose message and send it via given SMTP-Host
   153       String smtpHost = Config.getInstance().get(Config.MLSEND_HOST, "localhost");
   154       int    smtpPort = Config.getInstance().get(Config.MLSEND_PORT, 25);
   155       String smtpUser = Config.getInstance().get(Config.MLSEND_USER, "user");
   156       String smtpPw   = Config.getInstance().get(Config.MLSEND_PASSWORD, "mysecret");
   157 
   158       Properties props    = System.getProperties();
   159       props.put("mail.smtp.localhost", 
   160         Config.getInstance().get(Config.HOSTNAME, "localhost"));
   161       props.put("mail.smtp.from",  // Used for MAIL FROM command
   162         Config.getInstance().get(
   163           Config.MLSEND_ADDRESS, article.getHeader(Headers.FROM)[0]));
   164       props.put("mail.smtp.host", smtpHost);
   165       props.put("mail.smtp.port", smtpPort);
   166       props.put("mail.smtp.auth", "true");
   167 
   168       Address[] address = new Address[1];
   169       address[0] = new InternetAddress(listAddress);
   170 
   171       ArticleInputStream in = new ArticleInputStream(article);
   172       Session session = Session.getDefaultInstance(props, new PasswordAuthenticator());
   173       MimeMessage msg = new MimeMessage(session, in);
   174       msg.setRecipient(Message.RecipientType.TO, address[0]);
   175       msg.setReplyTo(address);
   176       msg.removeHeader(Headers.NEWSGROUPS);
   177       msg.removeHeader(Headers.PATH);
   178       msg.removeHeader(Headers.LINES);
   179       msg.removeHeader(Headers.BYTES);
   180       
   181       if(Config.getInstance().get(Config.MLSEND_RW_SENDER, false))
   182       {
   183         rewriteSenderAddress(msg); // Set the SENDER address
   184       }
   185       
   186       if(Config.getInstance().get(Config.MLSEND_RW_FROM, false))
   187       {
   188         rewriteFromAddress(msg);   // Set the FROM address
   189       }
   190       
   191       msg.saveChanges();
   192 
   193       // Send the mail
   194       Transport transport = session.getTransport("smtp");
   195       transport.connect(smtpHost, smtpPort, smtpUser, smtpPw);
   196       transport.sendMessage(msg, msg.getAllRecipients());
   197       transport.close();
   198 
   199       Stats.getInstance().mailGatewayed(article.getHeader(Headers.NEWSGROUPS)[0]);
   200       Log.msg("MLGateway: Mail " + article.getHeader("Subject")[0] 
   201         + " was delivered to " + listAddress + ".", true);
   202     }
   203   }
   204   
   205   /**
   206    * Sets the SENDER header of the given MimeMessage. This might be necessary
   207    * for moderated groups that does not allow the "normal" FROM sender.
   208    * @param msg
   209    * @throws javax.mail.MessagingException
   210    */
   211   private static void rewriteSenderAddress(MimeMessage msg)
   212     throws MessagingException
   213   {
   214     String mlAddress = Config.getInstance().get(Config.MLSEND_ADDRESS, null);
   215 
   216     if(mlAddress != null)
   217     {
   218       msg.setSender(new InternetAddress(mlAddress));
   219     }
   220     else
   221     {
   222       throw new MessagingException("Cannot rewrite SENDER header!");
   223     }
   224   }
   225   
   226   /**
   227    * Sets the FROM header of the given MimeMessage. This might be necessary
   228    * for moderated groups that does not allow the "normal" FROM sender.
   229    * @param msg
   230    * @throws javax.mail.MessagingException
   231    */
   232   private static void rewriteFromAddress(MimeMessage msg)
   233     throws MessagingException
   234   {
   235     Address[] froms  = msg.getFrom();
   236     String mlAddress = Config.getInstance().get(Config.MLSEND_ADDRESS, null);
   237 
   238     if(froms.length > 0 && froms[0] instanceof InternetAddress 
   239       && mlAddress != null)
   240     {
   241       InternetAddress from = (InternetAddress)froms[0];
   242       from.setAddress(mlAddress);
   243       msg.setFrom(from);
   244     }
   245     else
   246     {
   247       throw new MessagingException("Cannot rewrite FROM header!");
   248     }    
   249   }
   250   
   251 }