1 package org.paneris.messageboard.receivemail; 2 3 import java.net.InetAddress; 4 import java.net.ServerSocket; 5 import java.util.Properties; 6 7 import org.paneris.jal.model.DBConnectionManager; 8 import org.paneris.jal.model.Log; 9 import org.paneris.util.PropertiesUtils; 10 11 /** 12 * An SMTP server to handle mail coming in to messageboards. 13 * 14 * It is intended to be invoked from init scripts approximately thus: 15 * 16 * <PRE> 17 * java org.paneris.messageboard.receivemail.SMTPServer --port 1615 & 18 * </PRE> 19 * 20 * A single server can handle mail for messageboards in several 21 * separate databases; the name of the database to which it should 22 * connect is determined from the recipient address given when the 23 * mail arrives. The program looks for a `properties' resource under 24 * the name <TT>smtpServer.properties</TT> which specifies the mappings 25 * from domain to database name, in the form 26 * 27 * <PRE> 28 * org.paneris.messageboard.receivemail.database.DOMAIN=DATABASE 29 * </PRE> 30 * 31 * for example 32 * 33 * <PRE> 34 * org.paneris.messageboard.receivemail.database.messageboards.x.com=x 35 * </PRE> 36 * 37 * (see also <TT>smtpServer.properties.example</TT>). 38 * 39 * Mail can be funelled into the server either by having it listen on 40 * port 25 in place of sendmail, or by configuring the locally running 41 * MTA to forward appropriately addressed email to the server on 42 * a different port. 43 * 44 * <B>Snedmail configuration</B> 45 * Edit <TT>sendmail.cf</TT> to define a new mailer. Where it says 46 * 47 * <PRE> 48 * Msmtp, P=[IPC], F=mDFMuX, S=11/31, R=21, E=\r\n, L=990, 49 * T=DNS/RFC822/SMTP, 50 * A=IPC $h 51 * </PRE> 52 * 53 * insert also 54 * 55 * <PRE> 56 * Msmtp1615, P=[IPC], F=mDFMuX, S=11/31, R=21, E=\r\n, L=990, 57 * T=DNS/RFC822/SMTP, 58 * A=IPC $h 1615 59 * </PRE> 60 * 61 * Then use the standard <TT>mailertable</TT> feature to direct, for 62 * example, all mail to <TT>messageboards.x.com</TT> on to 63 * <TT>smtp1615:x.com</TT>. You can do this very easily with 64 * <TT>linuxconf</TT>'s <I>Special (domain) routing</I> menu: make an 65 * entry with <I>Destination</I> set to <TT>messageboards.x.com</TT>, 66 * <I>Forwarder</I> set to <TT>x.com</TT>, and <I>Mailer</I> set to 67 * <TT>smtp1615</TT>. But make sure to hack 68 * <TT>/usr/lib/linuxconf/mailconf/smtpmailer.std.cf</TT> first, as 69 * described above, to get it to define the special mailer in the 70 * <TT>sendmail.cf</TT> it generates. And of course for every mail 71 * domain which sendmail is configured to forward to the messageboards 72 * server, there should be an entry in <TT>smtpServer.properties</TT> 73 * telling the latter which database to use. 74 * 75 * <B>Qmail configuration</B> 76 * In <tt>...qmail/control/smtproutes</tt> add 77 * <pre> 78 * messageboards.paneris.org:127.0.0.1:1615 79 * </pre> 80 * 81 * <B>Postfix configuration</B> 82 * See http://www.postfix.org/transport.5.html 83 * 84 * In <tt>/etc/postfix/main.cf</tt> add 85 * <pre> 86 * transport_maps = hash:/etc/postfix/transport 87 * </pre> 88 * 89 * In <tt>/etc/postfix/transport</tt> add 90 * <pre> 91 * messageboards.paneris.org :127.0.0.1:1615 92 * </pre> 93 * (I found localhost went to a pipex server) 94 * you could equally use 95 * <pre> 96 * messageboards.paneris.org smtp:127.0.0.1:1615 97 * </pre> 98 * 99 * then run 100 * <pre> 101 * postmap /etc/postfix/transport 102 * postfix reload 103 * </pre> 104 * 105 * The program takes the following command line arguments: 106 * 107 * <TABLE> 108 * <TR> 109 * <TD><TT>--port <I>number</I></TT></TD> 110 * <TD>the port on which to listen, if not 1615</TD> 111 * </TR> 112 * <TR> 113 * <TD><TT>--properties <I>filename</I></TT></TD> 114 * <TD> 115 * the name of a file in <TT>CLASSPATH</TT> containing the 116 * domain-to-database mappings, if not 117 * <TT>smtpServer.properties</TT> 118 * </TD> 119 * </TR> 120 * <TR> 121 * <TD><TT>--log <I>filename</I></TT></TD> 122 * <TD> 123 * the name of the log file (defaults to 124 * <TT>/usr/local/apache/log/messageboard-receivemail.log</TT> 125 * </TD> 126 * </TR> 127 * </TABLE> 128 */ 129 130 public class SMTPServer { 131 132 private static final int portDefault = 1615; 133 private static final String propertiesNameDefault = "smtpServer.properties"; 134 private static final String logPathDefault = 135 "/usr/local/apache/logs/messageboard-receivemail.log"; 136 137 private static final String usage = 138 "Usage: ... [--port <port>] [--properties <resource>] [--log <file>]\n" + 139 " defaults --port " + portDefault + "\n" + 140 " --properties " + propertiesNameDefault + "\n" + 141 " --log " + logPathDefault; 142 143 public static void main(String[] args) { 144 145 System.out.println("Starting receive mail daemon"); 146 Log log = new Log("ReceiveMail", "ReceiveMail Log"); 147 148 int port = portDefault; 149 String propertiesName = propertiesNameDefault; 150 String logPath = null; 151 152 try { 153 for (int a = 0; a < args.length; ++a) { 154 if (args[a].equals("--port")) 155 port = Integer.parseInt(args[++a]); 156 else if (args[a].equals("--properties")) 157 propertiesName = args[++a]; 158 else if (args[a].equals("--log")) { 159 logPath = args[++a]; 160 try { 161 log.setTarget(logPath); 162 } 163 catch (Exception e) { 164 System.err.println(e); 165 System.exit(1); 166 } 167 } else throw new Exception(); 168 } 169 } 170 catch (Exception e) { 171 log.error(usage); 172 System.err.println(usage); 173 System.exit(1); 174 } 175 176 try { 177 if (logPath == null) { 178 // not set on command line 179 log.setTarget(logPathDefault); 180 } 181 System.out.println("log:"+logPath); 182 183 Properties databaseNameOfDomain = 184 PropertiesUtils.fromResource((new SMTPServer()).getClass(), 185 propertiesName); 186 187 DBConnectionManager connMgr = DBConnectionManager.getInstance(); 188 189 ServerSocket serverSocket = new ServerSocket(port); 190 for (;;) { 191 System.out.println("Starting new session"); 192 (new SMTPSession("messageboards." + 193 InetAddress.getLocalHost().getHostName(), 194 serverSocket.accept(), 195 connMgr, databaseNameOfDomain, 196 65536, log)).start(); 197 } 198 } 199 catch (Exception e) { 200 log.exception(e); 201 e.printStackTrace(); 202 System.exit(1); 203 } 204 } 205 }