3 * see AUTHORS for the list of contributors
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.
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.
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/>.
19 package org.sonews.mlgw;
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;
44 * Dispatches messages from mailing list or newsserver or vice versa.
45 * @author Christian Lins
48 public class Dispatcher
51 static class PasswordAuthenticator extends Authenticator
55 public PasswordAuthentication getPasswordAuthentication()
57 final String username =
58 Config.getInstance().get(Config.MLSEND_USER, "user");
59 final String password =
60 Config.getInstance().get(Config.MLSEND_PASSWORD, "mysecret");
62 return new PasswordAuthentication(username, password);
68 * Posts a message that was received from a mailing list to the
69 * appropriate newsgroup.
72 public static boolean toGroup(final Message msg)
76 Address[] to = msg.getAllRecipients(); // includes TO/CC/BCC
77 if(to == null || to.length <= 0)
79 Log.msg("Skipping message because no receipient!", true);
84 boolean posted = false;
85 for(Address toa : to) // Address can have '<' '>' around
87 if(!(toa instanceof InternetAddress))
91 String group = Database.getInstance()
92 .getGroupForList((InternetAddress)toa);
95 Log.msg("Posting to group " + group, true);
97 // Create new Article object
98 Article article = new Article(msg);
99 article.setGroup(group);
101 // Write article to database
102 if(!Database.getInstance().isArticleExisting(article.getMessageID()))
104 Database.getInstance().addArticle(article);
105 Stats.getInstance().mailGatewayed(
106 article.getHeader(Headers.NEWSGROUPS)[0]);
110 Log.msg("Article " + article.getMessageID() + " already existing.", true);
111 // TODO: It may be possible that a ML mail is posted to several
118 Log.msg("No group for " + toa, true);
126 ex.printStackTrace();
132 * Mails a message received through NNTP to the appropriate mailing list.
134 public static void toList(Article article)
135 throws IOException, MessagingException, SQLException
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(",");
141 for(String groupname : groupnames)
143 String listAddress = Database.getInstance().getListForGroup(groupname);
144 if(listAddress != null)
146 listAddresses.add(listAddress);
150 for(String listAddress : listAddresses)
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");
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");
168 Address[] address = new Address[1];
169 address[0] = new InternetAddress(listAddress);
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);
181 if(Config.getInstance().get(Config.MLSEND_RW_SENDER, false))
183 rewriteSenderAddress(msg); // Set the SENDER address
186 if(Config.getInstance().get(Config.MLSEND_RW_FROM, false))
188 rewriteFromAddress(msg); // Set the FROM address
194 Transport transport = session.getTransport("smtp");
195 transport.connect(smtpHost, smtpPort, smtpUser, smtpPw);
196 transport.sendMessage(msg, msg.getAllRecipients());
199 Stats.getInstance().mailGatewayed(article.getHeader(Headers.NEWSGROUPS)[0]);
200 Log.msg("MLGateway: Mail " + article.getHeader("Subject")[0]
201 + " was delivered to " + listAddress + ".", true);
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.
209 * @throws javax.mail.MessagingException
211 private static void rewriteSenderAddress(MimeMessage msg)
212 throws MessagingException
214 String mlAddress = Config.getInstance().get(Config.MLSEND_ADDRESS, null);
216 if(mlAddress != null)
218 msg.setSender(new InternetAddress(mlAddress));
222 throw new MessagingException("Cannot rewrite SENDER header!");
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.
230 * @throws javax.mail.MessagingException
232 private static void rewriteFromAddress(MimeMessage msg)
233 throws MessagingException
235 Address[] froms = msg.getFrom();
236 String mlAddress = Config.getInstance().get(Config.MLSEND_ADDRESS, null);
238 if(froms.length > 0 && froms[0] instanceof InternetAddress
239 && mlAddress != null)
241 InternetAddress from = (InternetAddress)froms[0];
242 from.setAddress(mlAddress);
247 throw new MessagingException("Cannot rewrite FROM header!");