src/org/sonews/mlgw/Dispatcher.java
changeset 42 7f84f4de2893
parent 36 c404a87db5b7
child 50 0bf10add82d9
     1.1 --- a/src/org/sonews/mlgw/Dispatcher.java	Sun Aug 29 17:43:58 2010 +0200
     1.2 +++ b/src/org/sonews/mlgw/Dispatcher.java	Mon Jun 06 20:12:21 2011 +0200
     1.3 @@ -43,267 +43,233 @@
     1.4   * @author Christian Lins
     1.5   * @since sonews/0.5.0
     1.6   */
     1.7 -public class Dispatcher 
     1.8 +public class Dispatcher
     1.9  {
    1.10  
    1.11 -  static class PasswordAuthenticator extends Authenticator
    1.12 -  {
    1.13 -    
    1.14 -    @Override
    1.15 -    public PasswordAuthentication getPasswordAuthentication()
    1.16 -    {
    1.17 -      final String username = 
    1.18 -        Config.inst().get(Config.MLSEND_USER, "user");
    1.19 -      final String password = 
    1.20 -        Config.inst().get(Config.MLSEND_PASSWORD, "mysecret");
    1.21 +	static class PasswordAuthenticator extends Authenticator
    1.22 +	{
    1.23  
    1.24 -      return new PasswordAuthentication(username, password);
    1.25 -    }
    1.26 -    
    1.27 -  }
    1.28 +		@Override
    1.29 +		public PasswordAuthentication getPasswordAuthentication()
    1.30 +		{
    1.31 +			final String username =
    1.32 +				Config.inst().get(Config.MLSEND_USER, "user");
    1.33 +			final String password =
    1.34 +				Config.inst().get(Config.MLSEND_PASSWORD, "mysecret");
    1.35  
    1.36 -  /**
    1.37 -   * Chunks out the email address of the full List-Post header field.
    1.38 -   * @param listPostValue
    1.39 -   * @return The matching email address or null
    1.40 -   */
    1.41 -  private static String chunkListPost(String listPostValue)
    1.42 -  {
    1.43 -    // listPostValue is of form "<mailto:dev@openoffice.org>"
    1.44 -    Pattern mailPattern = Pattern.compile("(\\w+[-|.])*\\w+@(\\w+.)+\\w+");
    1.45 -    Matcher mailMatcher = mailPattern.matcher(listPostValue);
    1.46 -    if(mailMatcher.find())
    1.47 -    {
    1.48 -      return listPostValue.substring(mailMatcher.start(), mailMatcher.end());
    1.49 -    }
    1.50 -    else
    1.51 -    {
    1.52 -      return null;
    1.53 -    }
    1.54 -  }
    1.55 +			return new PasswordAuthentication(username, password);
    1.56 +		}
    1.57 +	}
    1.58  
    1.59 -  /**
    1.60 -   * This method inspects the header of the given message, trying
    1.61 -   * to find the most appropriate recipient.
    1.62 -   * @param msg
    1.63 -   * @param fallback If this is false only List-Post and X-List-Post headers
    1.64 -   *                 are examined.
    1.65 -   * @return null or fitting group name for the given message.
    1.66 -   */
    1.67 -  private static List<String> getGroupFor(final Message msg, final boolean fallback)
    1.68 -    throws MessagingException, StorageBackendException
    1.69 -  {
    1.70 -    List<String> groups = null;
    1.71 +	/**
    1.72 +	 * Chunks out the email address of the full List-Post header field.
    1.73 +	 * @param listPostValue
    1.74 +	 * @return The matching email address or null
    1.75 +	 */
    1.76 +	private static String chunkListPost(String listPostValue)
    1.77 +	{
    1.78 +		// listPostValue is of form "<mailto:dev@openoffice.org>"
    1.79 +		Pattern mailPattern = Pattern.compile("(\\w+[-|.])*\\w+@(\\w+.)+\\w+");
    1.80 +		Matcher mailMatcher = mailPattern.matcher(listPostValue);
    1.81 +		if (mailMatcher.find()) {
    1.82 +			return listPostValue.substring(mailMatcher.start(), mailMatcher.end());
    1.83 +		} else {
    1.84 +			return null;
    1.85 +		}
    1.86 +	}
    1.87  
    1.88 -    // Is there a List-Post header?
    1.89 -    String[]        listPost = msg.getHeader(Headers.LIST_POST);
    1.90 -    InternetAddress listPostAddr;
    1.91 +	/**
    1.92 +	 * This method inspects the header of the given message, trying
    1.93 +	 * to find the most appropriate recipient.
    1.94 +	 * @param msg
    1.95 +	 * @param fallback If this is false only List-Post and X-List-Post headers
    1.96 +	 *                 are examined.
    1.97 +	 * @return null or fitting group name for the given message.
    1.98 +	 */
    1.99 +	private static List<String> getGroupFor(final Message msg, final boolean fallback)
   1.100 +		throws MessagingException, StorageBackendException
   1.101 +	{
   1.102 +		List<String> groups = null;
   1.103  
   1.104 -    if(listPost == null || listPost.length == 0 || "".equals(listPost[0]))
   1.105 -    {
   1.106 -      // Is there a X-List-Post header?
   1.107 -      listPost = msg.getHeader(Headers.X_LIST_POST);
   1.108 -    }
   1.109 +		// Is there a List-Post header?
   1.110 +		String[] listPost = msg.getHeader(Headers.LIST_POST);
   1.111 +		InternetAddress listPostAddr;
   1.112  
   1.113 -    if(listPost != null && listPost.length > 0 
   1.114 -      && !"".equals(listPost[0]) && chunkListPost(listPost[0]) != null)
   1.115 -    {
   1.116 -      // listPost[0] is of form "<mailto:dev@openoffice.org>"
   1.117 -      listPost[0]  = chunkListPost(listPost[0]);
   1.118 -      listPostAddr = new InternetAddress(listPost[0], false);
   1.119 -      groups = StorageManager.current().getGroupsForList(listPostAddr.getAddress());
   1.120 -    }
   1.121 -    else if(fallback)
   1.122 -    {
   1.123 -      Log.get().info("Using fallback recipient discovery for: " + msg.getSubject());
   1.124 -      groups = new ArrayList<String>();
   1.125 -      // Fallback to TO/CC/BCC addresses
   1.126 -      Address[] to = msg.getAllRecipients();
   1.127 -      for(Address toa : to) // Address can have '<' '>' around
   1.128 -      {
   1.129 -        if(toa instanceof InternetAddress)
   1.130 -        {
   1.131 -          List<String> g = StorageManager.current()
   1.132 -            .getGroupsForList(((InternetAddress)toa).getAddress());
   1.133 -          groups.addAll(g);
   1.134 -        }
   1.135 -      }
   1.136 -    }
   1.137 -    
   1.138 -    return groups;
   1.139 -  }
   1.140 -  
   1.141 -  /**
   1.142 -   * Posts a message that was received from a mailing list to the 
   1.143 -   * appropriate newsgroup.
   1.144 -   * If the message already exists in the storage, this message checks
   1.145 -   * if it must be posted in an additional group. This can happen for
   1.146 -   * crosspostings in different mailing lists.
   1.147 -   * @param msg
   1.148 -   */
   1.149 -  public static boolean toGroup(final Message msg)
   1.150 -  {
   1.151 -    if(msg == null)
   1.152 +		if (listPost == null || listPost.length == 0 || "".equals(listPost[0])) {
   1.153 +			// Is there a X-List-Post header?
   1.154 +			listPost = msg.getHeader(Headers.X_LIST_POST);
   1.155 +		}
   1.156 +
   1.157 +		if (listPost != null && listPost.length > 0
   1.158 +			&& !"".equals(listPost[0]) && chunkListPost(listPost[0]) != null) {
   1.159 +			// listPost[0] is of form "<mailto:dev@openoffice.org>"
   1.160 +			listPost[0] = chunkListPost(listPost[0]);
   1.161 +			listPostAddr = new InternetAddress(listPost[0], false);
   1.162 +			groups = StorageManager.current().getGroupsForList(listPostAddr.getAddress());
   1.163 +		} else if (fallback) {
   1.164 +			Log.get().info("Using fallback recipient discovery for: " + msg.getSubject());
   1.165 +			groups = new ArrayList<String>();
   1.166 +			// Fallback to TO/CC/BCC addresses
   1.167 +			Address[] to = msg.getAllRecipients();
   1.168 +			for (Address toa : to) // Address can have '<' '>' around
   1.169 +			{
   1.170 +				if (toa instanceof InternetAddress) {
   1.171 +					List<String> g = StorageManager.current().getGroupsForList(((InternetAddress) toa).getAddress());
   1.172 +					groups.addAll(g);
   1.173 +				}
   1.174 +			}
   1.175 +		}
   1.176 +
   1.177 +		return groups;
   1.178 +	}
   1.179 +
   1.180 +	/**
   1.181 +	 * Posts a message that was received from a mailing list to the
   1.182 +	 * appropriate newsgroup.
   1.183 +	 * If the message already exists in the storage, this message checks
   1.184 +	 * if it must be posted in an additional group. This can happen for
   1.185 +	 * crosspostings in different mailing lists.
   1.186 +	 * @param msg
   1.187 +	 */
   1.188 +	public static boolean toGroup(final Message msg)
   1.189  	{
   1.190 -      throw new IllegalArgumentException("Argument 'msg' must not be null!");
   1.191 -    }
   1.192 +		if (msg == null) {
   1.193 +			throw new IllegalArgumentException("Argument 'msg' must not be null!");
   1.194 +		}
   1.195  
   1.196 -    try
   1.197 -    {
   1.198 -      // Create new Article object
   1.199 -      Article article = new Article(msg);
   1.200 -      boolean posted  = false;
   1.201 +		try {
   1.202 +			// Create new Article object
   1.203 +			Article article = new Article(msg);
   1.204 +			boolean posted = false;
   1.205  
   1.206 -      // Check if this mail is already existing the storage
   1.207 -      boolean updateReq = 
   1.208 -        StorageManager.current().isArticleExisting(article.getMessageID());
   1.209 +			// Check if this mail is already existing the storage
   1.210 +			boolean updateReq =
   1.211 +				StorageManager.current().isArticleExisting(article.getMessageID());
   1.212  
   1.213 -      List<String> newsgroups = getGroupFor(msg, !updateReq);
   1.214 -      List<String> oldgroups  = new ArrayList<String>();
   1.215 -      if(updateReq)
   1.216 -      {
   1.217 -        // Check for duplicate entries of the same group
   1.218 -        Article oldArticle = StorageManager.current().getArticle(article.getMessageID());
   1.219 -        if(oldArticle != null)
   1.220 -		{
   1.221 -          List<Group> oldGroups = oldArticle.getGroups();
   1.222 -          for(Group oldGroup : oldGroups)
   1.223 -          {
   1.224 -            if(!newsgroups.contains(oldGroup.getName()))
   1.225 -            {
   1.226 -              oldgroups.add(oldGroup.getName());
   1.227 -            }
   1.228 -          }
   1.229 +			List<String> newsgroups = getGroupFor(msg, !updateReq);
   1.230 +			List<String> oldgroups = new ArrayList<String>();
   1.231 +			if (updateReq) {
   1.232 +				// Check for duplicate entries of the same group
   1.233 +				Article oldArticle = StorageManager.current().getArticle(article.getMessageID());
   1.234 +				if (oldArticle != null) {
   1.235 +					List<Group> oldGroups = oldArticle.getGroups();
   1.236 +					for (Group oldGroup : oldGroups) {
   1.237 +						if (!newsgroups.contains(oldGroup.getName())) {
   1.238 +							oldgroups.add(oldGroup.getName());
   1.239 +						}
   1.240 +					}
   1.241 +				}
   1.242 +			}
   1.243 +
   1.244 +			if (newsgroups.size() > 0) {
   1.245 +				newsgroups.addAll(oldgroups);
   1.246 +				StringBuilder groups = new StringBuilder();
   1.247 +				for (int n = 0; n < newsgroups.size(); n++) {
   1.248 +					groups.append(newsgroups.get(n));
   1.249 +					if (n + 1 != newsgroups.size()) {
   1.250 +						groups.append(',');
   1.251 +					}
   1.252 +				}
   1.253 +				Log.get().info("Posting to group " + groups.toString());
   1.254 +
   1.255 +				article.setGroup(groups.toString());
   1.256 +				//article.removeHeader(Headers.REPLY_TO);
   1.257 +				//article.removeHeader(Headers.TO);
   1.258 +
   1.259 +				// Write article to database
   1.260 +				if (updateReq) {
   1.261 +					Log.get().info("Updating " + article.getMessageID()
   1.262 +						+ " with additional groups");
   1.263 +					StorageManager.current().delete(article.getMessageID());
   1.264 +					StorageManager.current().addArticle(article);
   1.265 +				} else {
   1.266 +					Log.get().info("Gatewaying " + article.getMessageID() + " to "
   1.267 +						+ article.getHeader(Headers.NEWSGROUPS)[0]);
   1.268 +					StorageManager.current().addArticle(article);
   1.269 +					Stats.getInstance().mailGatewayed(
   1.270 +						article.getHeader(Headers.NEWSGROUPS)[0]);
   1.271 +				}
   1.272 +				posted = true;
   1.273 +			} else {
   1.274 +				StringBuilder buf = new StringBuilder();
   1.275 +				for (Address toa : msg.getAllRecipients()) {
   1.276 +					buf.append(' ');
   1.277 +					buf.append(toa.toString());
   1.278 +				}
   1.279 +				buf.append(" " + article.getHeader(Headers.LIST_POST)[0]);
   1.280 +				Log.get().warning("No group for" + buf.toString());
   1.281 +			}
   1.282 +			return posted;
   1.283 +		} catch (Exception ex) {
   1.284 +			ex.printStackTrace();
   1.285 +			return false;
   1.286  		}
   1.287 -      }
   1.288 +	}
   1.289  
   1.290 -      if(newsgroups.size() > 0)
   1.291 -      {
   1.292 -        newsgroups.addAll(oldgroups);
   1.293 -        StringBuilder groups = new StringBuilder();
   1.294 -        for(int n = 0; n < newsgroups.size(); n++)
   1.295 -        {
   1.296 -          groups.append(newsgroups.get(n));
   1.297 -          if (n + 1 != newsgroups.size())
   1.298 -          {
   1.299 -            groups.append(',');
   1.300 -          }
   1.301 -        }
   1.302 -        Log.get().info("Posting to group " + groups.toString());
   1.303 +	/**
   1.304 +	 * Mails a message received through NNTP to the appropriate mailing list.
   1.305 +	 * This method MAY be called several times by PostCommand for the same
   1.306 +	 * article.
   1.307 +	 */
   1.308 +	public static void toList(Article article, String group)
   1.309 +		throws IOException, MessagingException, StorageBackendException
   1.310 +	{
   1.311 +		// Get mailing lists for the group of this article
   1.312 +		List<String> rcptAddresses = StorageManager.current().getListsForGroup(group);
   1.313  
   1.314 -        article.setGroup(groups.toString());
   1.315 -        //article.removeHeader(Headers.REPLY_TO);
   1.316 -        //article.removeHeader(Headers.TO);
   1.317 +		if (rcptAddresses == null || rcptAddresses.size() == 0) {
   1.318 +			Log.get().warning("No ML-address for " + group + " found.");
   1.319 +			return;
   1.320 +		}
   1.321  
   1.322 -        // Write article to database
   1.323 -        if(updateReq)
   1.324 -        {
   1.325 -          Log.get().info("Updating " + article.getMessageID()
   1.326 -            + " with additional groups");
   1.327 -          StorageManager.current().delete(article.getMessageID());
   1.328 -          StorageManager.current().addArticle(article);
   1.329 -        }
   1.330 -        else
   1.331 -        {
   1.332 -          Log.get().info("Gatewaying " + article.getMessageID() + " to "
   1.333 -            + article.getHeader(Headers.NEWSGROUPS)[0]);
   1.334 -          StorageManager.current().addArticle(article);
   1.335 -          Stats.getInstance().mailGatewayed(
   1.336 -            article.getHeader(Headers.NEWSGROUPS)[0]);
   1.337 -        }
   1.338 -        posted = true;
   1.339 -      }
   1.340 -      else
   1.341 -      {
   1.342 -        StringBuilder buf = new StringBuilder();
   1.343 -        for (Address toa : msg.getAllRecipients())
   1.344 -        {
   1.345 -          buf.append(' ');
   1.346 -          buf.append(toa.toString());
   1.347 -        }
   1.348 -        buf.append(" " + article.getHeader(Headers.LIST_POST)[0]);
   1.349 -        Log.get().warning("No group for" + buf.toString());
   1.350 -      }
   1.351 -      return posted;
   1.352 -    }
   1.353 -    catch(Exception ex)
   1.354 -    {
   1.355 -      ex.printStackTrace();
   1.356 -      return false;
   1.357 -    }
   1.358 -  }
   1.359 -  
   1.360 -  /**
   1.361 -   * Mails a message received through NNTP to the appropriate mailing list.
   1.362 -   * This method MAY be called several times by PostCommand for the same
   1.363 -   * article.
   1.364 -   */
   1.365 -  public static void toList(Article article, String group)
   1.366 -    throws IOException, MessagingException, StorageBackendException
   1.367 -  {
   1.368 -    // Get mailing lists for the group of this article
   1.369 -    List<String> rcptAddresses = StorageManager.current().getListsForGroup(group);
   1.370 +		for (String rcptAddress : rcptAddresses) {
   1.371 +			// Compose message and send it via given SMTP-Host
   1.372 +			String smtpHost = Config.inst().get(Config.MLSEND_HOST, "localhost");
   1.373 +			int smtpPort = Config.inst().get(Config.MLSEND_PORT, 25);
   1.374 +			String smtpUser = Config.inst().get(Config.MLSEND_USER, "user");
   1.375 +			String smtpPw = Config.inst().get(Config.MLSEND_PASSWORD, "mysecret");
   1.376 +			String smtpFrom = Config.inst().get(
   1.377 +				Config.MLSEND_ADDRESS, article.getHeader(Headers.FROM)[0]);
   1.378  
   1.379 -    if(rcptAddresses == null || rcptAddresses.size() == 0)
   1.380 -    {
   1.381 -      Log.get().warning("No ML-address for " + group + " found.");
   1.382 -      return;
   1.383 -    }
   1.384 +			// TODO: Make Article cloneable()
   1.385 +			article.getMessageID(); // Make sure an ID is existing
   1.386 +			article.removeHeader(Headers.NEWSGROUPS);
   1.387 +			article.removeHeader(Headers.PATH);
   1.388 +			article.removeHeader(Headers.LINES);
   1.389 +			article.removeHeader(Headers.BYTES);
   1.390  
   1.391 -    for(String rcptAddress : rcptAddresses)
   1.392 -    {
   1.393 -      // Compose message and send it via given SMTP-Host
   1.394 -      String smtpHost = Config.inst().get(Config.MLSEND_HOST, "localhost");
   1.395 -      int smtpPort = Config.inst().get(Config.MLSEND_PORT, 25);
   1.396 -      String smtpUser = Config.inst().get(Config.MLSEND_USER, "user");
   1.397 -      String smtpPw = Config.inst().get(Config.MLSEND_PASSWORD, "mysecret");
   1.398 -      String smtpFrom = Config.inst().get(
   1.399 -        Config.MLSEND_ADDRESS, article.getHeader(Headers.FROM)[0]);
   1.400 +			article.setHeader("To", rcptAddress);
   1.401 +			//article.setHeader("Reply-To", listAddress);
   1.402  
   1.403 -      // TODO: Make Article cloneable()
   1.404 -      article.getMessageID(); // Make sure an ID is existing
   1.405 -      article.removeHeader(Headers.NEWSGROUPS);
   1.406 -      article.removeHeader(Headers.PATH);
   1.407 -      article.removeHeader(Headers.LINES);
   1.408 -      article.removeHeader(Headers.BYTES);
   1.409 +			if (Config.inst().get(Config.MLSEND_RW_SENDER, false)) {
   1.410 +				rewriteSenderAddress(article); // Set the SENDER address
   1.411 +			}
   1.412  
   1.413 -      article.setHeader("To", rcptAddress);
   1.414 -      //article.setHeader("Reply-To", listAddress);
   1.415 +			SMTPTransport smtpTransport = new SMTPTransport(smtpHost, smtpPort);
   1.416 +			smtpTransport.send(article, smtpFrom, rcptAddress);
   1.417 +			smtpTransport.close();
   1.418  
   1.419 -      if (Config.inst().get(Config.MLSEND_RW_SENDER, false))
   1.420 -      {
   1.421 -        rewriteSenderAddress(article); // Set the SENDER address
   1.422 -      }
   1.423 +			Stats.getInstance().mailGatewayed(group);
   1.424 +			Log.get().info("MLGateway: Mail " + article.getHeader("Subject")[0]
   1.425 +				+ " was delivered to " + rcptAddress + ".");
   1.426 +		}
   1.427 +	}
   1.428  
   1.429 -      SMTPTransport smtpTransport = new SMTPTransport(smtpHost, smtpPort);
   1.430 -      smtpTransport.send(article, smtpFrom, rcptAddress);
   1.431 -      smtpTransport.close();
   1.432 +	/**
   1.433 +	 * Sets the SENDER header of the given MimeMessage. This might be necessary
   1.434 +	 * for moderated groups that does not allow the "normal" FROM sender.
   1.435 +	 * @param msg
   1.436 +	 * @throws javax.mail.MessagingException
   1.437 +	 */
   1.438 +	private static void rewriteSenderAddress(Article msg)
   1.439 +		throws MessagingException
   1.440 +	{
   1.441 +		String mlAddress = Config.inst().get(Config.MLSEND_ADDRESS, null);
   1.442  
   1.443 -      Stats.getInstance().mailGatewayed(group);
   1.444 -      Log.get().info("MLGateway: Mail " + article.getHeader("Subject")[0]
   1.445 -        + " was delivered to " + rcptAddress + ".");
   1.446 -    }
   1.447 -  }
   1.448 -  
   1.449 -  /**
   1.450 -   * Sets the SENDER header of the given MimeMessage. This might be necessary
   1.451 -   * for moderated groups that does not allow the "normal" FROM sender.
   1.452 -   * @param msg
   1.453 -   * @throws javax.mail.MessagingException
   1.454 -   */
   1.455 -  private static void rewriteSenderAddress(Article msg)
   1.456 -    throws MessagingException
   1.457 -  {
   1.458 -    String mlAddress = Config.inst().get(Config.MLSEND_ADDRESS, null);
   1.459 -
   1.460 -    if(mlAddress != null)
   1.461 -    {
   1.462 -      msg.setHeader(Headers.SENDER, mlAddress);
   1.463 -    }
   1.464 -    else
   1.465 -    {
   1.466 -      throw new MessagingException("Cannot rewrite SENDER header!");
   1.467 -    }
   1.468 -  }
   1.469 -  
   1.470 +		if (mlAddress != null) {
   1.471 +			msg.setHeader(Headers.SENDER, mlAddress);
   1.472 +		} else {
   1.473 +			throw new MessagingException("Cannot rewrite SENDER header!");
   1.474 +		}
   1.475 +	}
   1.476  }