View Javadoc
1   /*
2    * DavMail POP/IMAP/SMTP/CalDav/LDAP Exchange Gateway
3    * Copyright (C) 2009  Mickael Guessant
4    *
5    * This program is free software; you can redistribute it and/or
6    * modify it under the terms of the GNU General Public License
7    * as published by the Free Software Foundation; either version 2
8    * of the License, or (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, write to the Free Software
17   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18   */
19  package davmail;
20  
21  import davmail.caldav.CaldavServer;
22  import davmail.exception.DavMailException;
23  import davmail.exchange.ExchangeSessionFactory;
24  import davmail.exchange.auth.ExchangeAuthenticator;
25  import davmail.http.HttpClientAdapter;
26  import davmail.http.request.GetRequest;
27  import davmail.imap.ImapServer;
28  import davmail.ldap.LdapServer;
29  import davmail.pop.PopServer;
30  import davmail.smtp.SmtpServer;
31  import davmail.ui.tray.DavGatewayTray;
32  import org.apache.log4j.Logger;
33  
34  import java.awt.*;
35  import java.io.IOException;
36  import java.lang.reflect.InvocationTargetException;
37  import java.util.ArrayList;
38  
39  /**
40   * DavGateway main class
41   */
42  public final class DavGateway {
43      private static final Logger LOGGER = Logger.getLogger(DavGateway.class);
44      private static final String HTTP_DAVMAIL_SOURCEFORGE_NET_VERSION_TXT = "https://davmail.sourceforge.net/version.txt";
45  
46      private static final Object LOCK = new Object();
47      private static boolean shutdown = false;
48  
49      private DavGateway() {
50      }
51  
52      private static final ArrayList<AbstractServer> SERVER_LIST = new ArrayList<>();
53  
54      /**
55       * Start the gateway, listen on specified smtp and pop3 ports
56       *
57       * @param args command line parameter config file path
58       */
59      public static void main(String[] args) {
60          boolean notray = false;
61          boolean server = false;
62          boolean token = false;
63  
64          // check environment for davmail settings path in Docker
65          String configFilePath = Settings.getConfigFilePath();
66          for (String arg : args) {
67              if (arg.startsWith("-")) {
68                  if ("-notray".equals(arg)) {
69                      notray = true;
70                  } else if ("-server".equals(arg)) {
71                      server = true;
72                  } else if ("-token".equals(arg)) {
73                      token = true;
74                  }
75              } else {
76                  configFilePath = arg;
77              }
78          }
79  
80          Settings.setConfigFilePath(configFilePath);
81          Settings.load();
82          if (token) {
83              try {
84                  ExchangeAuthenticator authenticator = (ExchangeAuthenticator) Class.forName("davmail.exchange.auth.O365InteractiveAuthenticator")
85                          .getDeclaredConstructor().newInstance();
86                  authenticator.setUsername("");
87                  authenticator.authenticate();
88                  System.out.println(authenticator.getToken().getRefreshToken());
89              } catch (IOException | ClassNotFoundException | NoSuchMethodException | InstantiationException |
90                       IllegalAccessException | InvocationTargetException e) {
91                  System.err.println(e+" "+e.getMessage());
92              }
93              // force shutdown on Linux
94              System.exit(0);
95          } else {
96  
97              if (GraphicsEnvironment.isHeadless()) {
98                  // force server mode
99                  LOGGER.debug("Headless mode, do not create GUI");
100                 server = true;
101             }
102             if (server) {
103                 Settings.setProperty("davmail.server", "true");
104                 Settings.updateLoggingConfig();
105             }
106 
107 
108             if (Settings.getBooleanProperty("davmail.server")) {
109                 LOGGER.debug("Start DavMail in server mode");
110             } else {
111                 LOGGER.debug("Start DavMail in GUI mode");
112                 DavGatewayTray.init(notray);
113             }
114 
115             start();
116 
117             // server mode: all threads are daemon threads, do not let main stop
118             if (Settings.getBooleanProperty("davmail.server")) {
119                 Runtime.getRuntime().addShutdownHook(new Thread("Shutdown") {
120                     @Override
121                     public void run() {
122                         shutdown = true;
123                         DavGatewayTray.debug(new BundleMessage("LOG_GATEWAY_INTERRUPTED"));
124                         DavGateway.stop();
125                         synchronized (LOCK) {
126                             LOCK.notifyAll();
127                         }
128                     }
129                 });
130 
131                 synchronized (LOCK) {
132                     try {
133                         while (!shutdown) {
134                             LOCK.wait();
135                         }
136                     } catch (InterruptedException e) {
137                         DavGatewayTray.debug(new BundleMessage("LOG_GATEWAY_INTERRUPTED"));
138                         Thread.currentThread().interrupt();
139                     }
140                 }
141 
142             }
143         }
144     }
145 
146     /**
147      * Start DavMail listeners.
148      */
149     public static void start() {
150         SERVER_LIST.clear();
151 
152         int smtpPort = Settings.getIntProperty("davmail.smtpPort");
153         if (smtpPort != 0) {
154             SERVER_LIST.add(new SmtpServer(smtpPort));
155         }
156         int popPort = Settings.getIntProperty("davmail.popPort");
157         if (popPort != 0) {
158             SERVER_LIST.add(new PopServer(popPort));
159         }
160         int imapPort = Settings.getIntProperty("davmail.imapPort");
161         if (imapPort != 0) {
162             SERVER_LIST.add(new ImapServer(imapPort));
163         }
164         int caldavPort = Settings.getIntProperty("davmail.caldavPort");
165         if (caldavPort != 0) {
166             SERVER_LIST.add(new CaldavServer(caldavPort));
167         }
168         int ldapPort = Settings.getIntProperty("davmail.ldapPort");
169         if (ldapPort != 0) {
170             SERVER_LIST.add(new LdapServer(ldapPort));
171         }
172 
173         BundleMessage.BundleMessageList messages = new BundleMessage.BundleMessageList();
174         BundleMessage.BundleMessageList errorMessages = new BundleMessage.BundleMessageList();
175         for (AbstractServer server : SERVER_LIST) {
176             try {
177                 server.bind();
178                 server.start();
179                 messages.add(new BundleMessage("LOG_PROTOCOL_PORT", server.getProtocolName(), server.getPort()));
180             } catch (DavMailException e) {
181                 errorMessages.add(e.getBundleMessage());
182             }
183         }
184 
185         final String currentVersion = getCurrentVersion();
186         boolean showStartupBanner = Settings.getBooleanProperty("davmail.showStartupBanner", true);
187         if (showStartupBanner) {
188             DavGatewayTray.info(new BundleMessage("LOG_DAVMAIL_GATEWAY_LISTENING", currentVersion, messages));
189         }
190         if (!errorMessages.isEmpty()) {
191             DavGatewayTray.error(new BundleMessage("LOG_MESSAGE", errorMessages));
192         }
193 
194         // check for new version in a separate thread
195         new Thread("CheckRelease") {
196             @Override
197             public void run() {
198                 String releasedVersion = getReleasedVersion();
199                 if (!currentVersion.isEmpty() && releasedVersion != null && currentVersion.compareTo(releasedVersion) < 0) {
200                     DavGatewayTray.info(new BundleMessage("LOG_NEW_VERSION_AVAILABLE", releasedVersion));
201                 }
202 
203             }
204         }.start();
205 
206     }
207 
208     /**
209      * Stop all listeners, shutdown connection pool and clear session cache.
210      */
211     public static void stop() {
212         DavGateway.stopServers();
213         // close pooled connections
214         ExchangeSessionFactory.shutdown();
215         DavGatewayTray.info(new BundleMessage("LOG_GATEWAY_STOP"));
216         DavGatewayTray.dispose();
217     }
218 
219     /**
220      * Stop all listeners and clear session cache.
221      */
222     public static void restart() {
223         DavGateway.stopServers();
224         // clear session cache
225         ExchangeSessionFactory.shutdown();
226         DavGateway.start();
227     }
228 
229     private static void stopServers() {
230         for (AbstractServer server : SERVER_LIST) {
231             server.close();
232             try {
233                 server.join();
234             } catch (InterruptedException e) {
235                 DavGatewayTray.warn(new BundleMessage("LOG_EXCEPTION_WAITING_SERVER_THREAD_DIE"), e);
236                 Thread.currentThread().interrupt();
237             }
238         }
239     }
240 
241     /**
242      * Get current DavMail version.
243      *
244      * @return current version
245      */
246     public static String getCurrentVersion() {
247         Package davmailPackage = DavGateway.class.getPackage();
248         String currentVersion = davmailPackage.getImplementationVersion();
249         if (currentVersion == null) {
250             currentVersion = "";
251         }
252         return currentVersion;
253     }
254 
255     /**
256      * Get latest released version from SourceForge.
257      *
258      * @return latest version
259      */
260     public static String getReleasedVersion() {
261         String version = null;
262         if (!Settings.getBooleanProperty("davmail.disableUpdateCheck")) {
263             try (HttpClientAdapter httpClientAdapter = new HttpClientAdapter(HTTP_DAVMAIL_SOURCEFORGE_NET_VERSION_TXT)) {
264                 GetRequest getRequest = new GetRequest(HTTP_DAVMAIL_SOURCEFORGE_NET_VERSION_TXT);
265                 getRequest.setHeader("User-Agent", "Mozilla/5.0");
266                 getRequest = httpClientAdapter.executeFollowRedirect(getRequest);
267                 version = getRequest.getResponseBodyAsString();
268                 LOGGER.debug("DavMail released version: " + version);
269             } catch (IOException e) {
270                 DavGatewayTray.debug(new BundleMessage("LOG_UNABLE_TO_GET_RELEASED_VERSION"));
271             }
272         }
273         return version;
274     }
275 }