Shinsuke Sugaya 9 лет назад
Родитель
Сommit
ef95d859b8

+ 47 - 0
src/main/java/org/codelibs/fess/app/web/admin/general/AdminGeneralAction.java

@@ -15,6 +15,8 @@
  */
 package org.codelibs.fess.app.web.admin.general;
 
+import java.net.InetAddress;
+import java.net.UnknownHostException;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -22,16 +24,23 @@ import java.util.Map;
 
 import javax.annotation.Resource;
 
+import org.codelibs.core.beans.util.BeanUtil;
 import org.codelibs.core.lang.StringUtil;
 import org.codelibs.core.misc.DynamicProperties;
 import org.codelibs.fess.Constants;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.helper.SystemHelper;
+import org.codelibs.fess.mylasta.direction.FessConfig;
+import org.codelibs.fess.mylasta.mail.TestmailPostcard;
 import org.codelibs.fess.util.ComponentUtil;
+import org.codelibs.fess.util.StreamUtil;
+import org.lastaflute.core.mail.Postbox;
 import org.lastaflute.web.Execute;
 import org.lastaflute.web.response.HtmlResponse;
 import org.lastaflute.web.ruts.process.ActionRuntime;
 import org.lastaflute.web.util.LaRequestUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * @author shinsuke
@@ -39,6 +48,8 @@ import org.lastaflute.web.util.LaRequestUtil;
  */
 public class AdminGeneralAction extends FessAdminAction {
 
+    private static final Logger logger = LoggerFactory.getLogger(AdminGeneralAction.class);
+
     // ===================================================================================
     //                                                                           Attribute
     //                                                                           =========
@@ -71,6 +82,42 @@ public class AdminGeneralAction extends FessAdminAction {
         });
     }
 
+    @Execute
+    public HtmlResponse sendmail(final MailForm form) {
+        validate(form, messages -> {}, () -> {
+            return asHtml(path_AdminGeneral_AdminGeneralJsp);
+        });
+
+        final String[] toAddresses = form.notificationTo.split(",");
+        final Map<String, Object> dataMap = new HashMap<String, Object>();
+        try {
+            dataMap.put("hostname", InetAddress.getLocalHost().getHostAddress());
+        } catch (final UnknownHostException e) {
+            dataMap.put("hostname", "UNKNOWN");
+        }
+
+        final FessConfig fessConfig = ComponentUtil.getComponent(FessConfig.class);
+        final Postbox postbox = ComponentUtil.getComponent(Postbox.class);
+        try {
+            TestmailPostcard.droppedInto(postbox, postcard -> {
+                postcard.setFrom(fessConfig.getMailFromAddress(), fessConfig.getMailFromName());
+                postcard.addReplyTo(fessConfig.getMailReturnPath());
+                StreamUtil.of(toAddresses).forEach(address -> {
+                    postcard.addTo(address);
+                });
+                BeanUtil.copyMapToBean(dataMap, postcard);
+            });
+            saveInfo(messages -> messages.addSuccessSendTestmail(GLOBAL));
+            updateProperty(Constants.NOTIFICATION_TO_PROPERTY, form.notificationTo);
+            crawlerProperties.store();
+        } catch (Exception e) {
+            logger.warn("Failed to send a test mail.", e);
+            saveError(messages -> messages.addErrorsFailedToSendTestmail(GLOBAL));
+        }
+
+        return redirectByParam(AdminGeneralAction.class, "notificationTo", form.notificationTo);
+    }
+
     @Execute
     public HtmlResponse update(final EditForm form) {
         validate(form, messages -> {}, () -> {

+ 77 - 0
src/main/java/org/codelibs/fess/app/web/admin/general/MailForm.java

@@ -0,0 +1,77 @@
+/*
+ * Copyright 2012-2015 CodeLibs Project and the Others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ */
+package org.codelibs.fess.app.web.admin.general;
+
+import java.io.Serializable;
+
+import javax.validation.constraints.Size;
+
+import org.lastaflute.web.validation.Required;
+
+/**
+ * @author shinsuke
+ */
+public class MailForm implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    public String incrementalCrawling;
+
+    public String dayForCleanup;
+
+    public String crawlingThreadCount;
+
+    public String searchLog;
+
+    public String userInfo;
+
+    public String userFavorite;
+
+    public String webApiJson;
+
+    public String defaultLabelValue;
+
+    public String appendQueryParameter;
+
+    public String supportedSearch;
+
+    public String ignoreFailureType;
+
+    public String failureCountThreshold;
+
+    public String hotSearchWord;
+
+    public String csvFileEncoding;
+
+    public String purgeSearchLogDay;
+
+    public String purgeJobLogDay;
+
+    public String purgeUserInfoDay;
+
+    public String purgeByBots;
+
+    @Required
+    @Size(max = 1000)
+    public String notificationTo;
+
+    public String suggestSearchLog;
+
+    public String suggestDocuments;
+
+    public String purgeSuggestSearchLogDay;
+
+}

+ 10 - 14
src/main/java/org/codelibs/fess/exec/Crawler.java

@@ -274,7 +274,7 @@ public class Crawler implements Serializable {
         }
     }
 
-    public void sendMail(final Map<String, String> infoMap) {
+    protected void sendMail(final Map<String, String> infoMap) {
         final String toStrs = (String) crawlerProperties.get(Constants.NOTIFICATION_TO_PROPERTY);
         if (StringUtil.isNotBlank(toStrs)) {
             final String[] toAddresses = toStrs.split(",");
@@ -292,20 +292,16 @@ public class Crawler implements Serializable {
                 // ignore
             }
 
-            try {
-                final FessConfig fessConfig = ComponentUtil.getComponent(FessConfig.class);
-                final Postbox postbox = ComponentUtil.getComponent(Postbox.class);
-                CrawlerPostcard.droppedInto(postbox, postcard -> {
-                    postcard.setFrom(fessConfig.getMailFromAddress(), fessConfig.getMailFromName());
-                    postcard.addReplyTo(fessConfig.getMailReturnPath());
-                    StreamUtil.of(toAddresses).forEach(address -> {
-                        postcard.addTo(address);
-                    });
-                    BeanUtil.copyMapToBean(dataMap, postcard);
+            final FessConfig fessConfig = ComponentUtil.getComponent(FessConfig.class);
+            final Postbox postbox = ComponentUtil.getComponent(Postbox.class);
+            CrawlerPostcard.droppedInto(postbox, postcard -> {
+                postcard.setFrom(fessConfig.getMailFromAddress(), fessConfig.getMailFromName());
+                postcard.addReplyTo(fessConfig.getMailReturnPath());
+                StreamUtil.of(toAddresses).forEach(address -> {
+                    postcard.addTo(address);
                 });
-            } catch (final Exception e) {
-                logger.warn("Failed to send the notification.", e);
-            }
+                BeanUtil.copyMapToBean(dataMap, postcard);
+            });
         }
     }
 

+ 6 - 3
src/main/java/org/codelibs/fess/mylasta/action/FessLabels.java

@@ -1232,13 +1232,13 @@ public class FessLabels extends ActionMessages {
     /** The key of the message: Upload File */
     public static final String LABELS_design_file = "{labels.design_file}";
 
-    /** The key of the message: Upload File Name (Optional) */
+    /** The key of the message: File Name (Optional) */
     public static final String LABELS_design_file_name = "{labels.design_file_name}";
 
     /** The key of the message: Upload */
     public static final String LABELS_design_button_upload = "{labels.design_button_upload}";
 
-    /** The key of the message: Page View Files */
+    /** The key of the message: JSP Files */
     public static final String LABELS_design_file_title_edit = "{labels.design_file_title_edit}";
 
     /** The key of the message: Edit */
@@ -1298,7 +1298,7 @@ public class FessLabels extends ActionMessages {
     /** The key of the message: Error Page (BadRequest) */
     public static final String LABELS_design_file_errorBadRequest = "{labels.design_file_errorBadRequest}";
 
-    /** The key of the message: Edit Page View File */
+    /** The key of the message: Edit JSP File */
     public static final String LABELS_design_title_edit_content = "{labels.design_title_edit_content}";
 
     /** The key of the message: Update */
@@ -1974,6 +1974,9 @@ public class FessLabels extends ActionMessages {
     /** The key of the message: Suggest */
     public static final String LABELS_general_menu_suggest = "{labels.general_menu_suggest}";
 
+    /** The key of the message: Send TestMail */
+    public static final String LABELS_send_testmail = "{labels.send_testmail}";
+
     /**
      * Assert the property is not null.
      * @param property The value of the property. (NotNull)

+ 34 - 0
src/main/java/org/codelibs/fess/mylasta/action/FessMessages.java

@@ -263,6 +263,9 @@ public class FessMessages extends FessLabels {
     /** The key of the message: Failed to delete document. */
     public static final String ERRORS_failed_to_delete_doc_in_admin = "{errors.failed_to_delete_doc_in_admin}";
 
+    /** The key of the message: Failed to send the test mail. */
+    public static final String ERRORS_failed_to_send_testmail = "{errors.failed_to_send_testmail}";
+
     /** The key of the message: The given query has unknown condition. */
     public static final String ERRORS_invalid_query_unknown = "{errors.invalid_query_unknown}";
 
@@ -332,6 +335,9 @@ public class FessMessages extends FessLabels {
     /** The key of the message: Uploaded Bad Word file. */
     public static final String SUCCESS_upload_bad_word = "{success.upload_bad_word}";
 
+    /** The key of the message: Sent the test mail. */
+    public static final String SUCCESS_send_testmail = "{success.send_testmail}";
+
     /** The key of the message: Created data. */
     public static final String SUCCESS_crud_create_crud_table = "{success.crud_create_crud_table}";
 
@@ -1513,6 +1519,20 @@ public class FessMessages extends FessLabels {
         return this;
     }
 
+    /**
+     * Add the created action message for the key 'errors.failed_to_send_testmail' with parameters.
+     * <pre>
+     * message: Failed to send the test mail.
+     * </pre>
+     * @param property The property name for the message. (NotNull)
+     * @return this. (NotNull)
+     */
+    public FessMessages addErrorsFailedToSendTestmail(String property) {
+        assertPropertyNotNull(property);
+        add(property, new ActionMessage(ERRORS_failed_to_send_testmail));
+        return this;
+    }
+
     /**
      * Add the created action message for the key 'errors.invalid_query_unknown' with parameters.
      * <pre>
@@ -1847,6 +1867,20 @@ public class FessMessages extends FessLabels {
         return this;
     }
 
+    /**
+     * Add the created action message for the key 'success.send_testmail' with parameters.
+     * <pre>
+     * message: Sent the test mail.
+     * </pre>
+     * @param property The property name for the message. (NotNull)
+     * @return this. (NotNull)
+     */
+    public FessMessages addSuccessSendTestmail(String property) {
+        assertPropertyNotNull(property);
+        add(property, new ActionMessage(SUCCESS_send_testmail));
+        return this;
+    }
+
     /**
      * Add the created action message for the key 'success.crud_create_crud_table' with parameters.
      * <pre>

+ 44 - 4
src/main/java/org/codelibs/fess/mylasta/direction/FessConfig.java

@@ -40,10 +40,30 @@ public interface FessConfig extends FessEnv {
     /** The key of the configuration. e.g. sha256 */
     String APP_DIGEST_ALGORISM = "app.digest.algorism";
 
-    /** The key of the configuration. e.g. -Djava.awt.headless=true-server-Xmx256m-XX:MaxMetaspaceSize=128m-XX:CompressedClassSpaceSize=32m-XX:-UseGCOverheadLimit-XX:+UseConcMarkSweepGC-XX:CMSInitiatingOccupancyFraction=75-XX:+UseParNewGC-XX:+UseTLAB-XX:+DisableExplicitGC */
+    /** The key of the configuration. e.g. -Djava.awt.headless=true
+    -server
+    -Xmx256m
+    -XX:MaxMetaspaceSize=128m
+    -XX:CompressedClassSpaceSize=32m
+    -XX:-UseGCOverheadLimit
+    -XX:+UseConcMarkSweepGC
+    -XX:CMSInitiatingOccupancyFraction=75
+    -XX:+UseParNewGC
+    -XX:+UseTLAB
+    -XX:+DisableExplicitGC */
     String JVM_CRAWLER_OPTIONS = "jvm.crawler.options";
 
-    /** The key of the configuration. e.g. -Djava.awt.headless=true-server-Xmx256m-XX:MaxMetaspaceSize=128m-XX:CompressedClassSpaceSize=32m-XX:-UseGCOverheadLimit-XX:+UseConcMarkSweepGC-XX:CMSInitiatingOccupancyFraction=75-XX:+UseParNewGC-XX:+UseTLAB-XX:+DisableExplicitGC */
+    /** The key of the configuration. e.g. -Djava.awt.headless=true
+    -server
+    -Xmx256m
+    -XX:MaxMetaspaceSize=128m
+    -XX:CompressedClassSpaceSize=32m
+    -XX:-UseGCOverheadLimit
+    -XX:+UseConcMarkSweepGC
+    -XX:CMSInitiatingOccupancyFraction=75
+    -XX:+UseParNewGC
+    -XX:+UseTLAB
+    -XX:+DisableExplicitGC */
     String JVM_SUGGEST_OPTIONS = "jvm.suggest.options";
 
     /** The key of the configuration. e.g. false */
@@ -415,7 +435,17 @@ public interface FessConfig extends FessEnv {
 
     /**
      * Get the value for the key 'jvm.crawler.options'. <br>
-     * The value is, e.g. -Djava.awt.headless=true-server-Xmx256m-XX:MaxMetaspaceSize=128m-XX:CompressedClassSpaceSize=32m-XX:-UseGCOverheadLimit-XX:+UseConcMarkSweepGC-XX:CMSInitiatingOccupancyFraction=75-XX:+UseParNewGC-XX:+UseTLAB-XX:+DisableExplicitGC <br>
+     * The value is, e.g. -Djava.awt.headless=true
+    -server
+    -Xmx256m
+    -XX:MaxMetaspaceSize=128m
+    -XX:CompressedClassSpaceSize=32m
+    -XX:-UseGCOverheadLimit
+    -XX:+UseConcMarkSweepGC
+    -XX:CMSInitiatingOccupancyFraction=75
+    -XX:+UseParNewGC
+    -XX:+UseTLAB
+    -XX:+DisableExplicitGC <br>
      * comment: JVM options
      * @return The value of found property. (NotNull: if not found, exception but basically no way)
      */
@@ -423,7 +453,17 @@ public interface FessConfig extends FessEnv {
 
     /**
      * Get the value for the key 'jvm.suggest.options'. <br>
-     * The value is, e.g. -Djava.awt.headless=true-server-Xmx256m-XX:MaxMetaspaceSize=128m-XX:CompressedClassSpaceSize=32m-XX:-UseGCOverheadLimit-XX:+UseConcMarkSweepGC-XX:CMSInitiatingOccupancyFraction=75-XX:+UseParNewGC-XX:+UseTLAB-XX:+DisableExplicitGC <br>
+     * The value is, e.g. -Djava.awt.headless=true
+    -server
+    -Xmx256m
+    -XX:MaxMetaspaceSize=128m
+    -XX:CompressedClassSpaceSize=32m
+    -XX:-UseGCOverheadLimit
+    -XX:+UseConcMarkSweepGC
+    -XX:CMSInitiatingOccupancyFraction=75
+    -XX:+UseParNewGC
+    -XX:+UseTLAB
+    -XX:+DisableExplicitGC <br>
      * @return The value of found property. (NotNull: if not found, exception but basically no way)
      */
     String getJvmSuggestOptions();

+ 109 - 0
src/main/java/org/codelibs/fess/mylasta/mail/TestmailPostcard.java

@@ -0,0 +1,109 @@
+/*
+ * Copyright 2012-2015 CodeLibs Project and the Others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ */
+package org.codelibs.fess.mylasta.mail;
+
+import org.lastaflute.core.mail.LaTypicalPostcard;
+import org.lastaflute.core.mail.MPCall;
+import org.lastaflute.core.mail.Postbox;
+
+/**
+ * The postcard for MailFlute on LastaFlute.
+ * @author FreeGen
+ */
+public class TestmailPostcard extends LaTypicalPostcard {
+
+    // ===================================================================================
+    //                                                                          Definition
+    //                                                                          ==========
+    public static final String PATH = "testmail.dfmail";
+
+    // ===================================================================================
+    //                                                                         Entry Point
+    //                                                                         ===========
+    public static TestmailPostcard droppedInto(Postbox postbox, MPCall<TestmailPostcard> postcardLambda) {
+        TestmailPostcard postcard = new TestmailPostcard();
+        postcardLambda.write(postcard);
+        postbox.post(postcard);
+        return postcard;
+    }
+
+    // ===================================================================================
+    //                                                                           Meta Data
+    //                                                                           =========
+    @Override
+    protected String getBodyFile() {
+        return PATH;
+    }
+
+    @Override
+    protected String[] getPropertyNames() {
+        return new String[] { "hostname" };
+    }
+
+    // ===================================================================================
+    //                                                                    Postcard Request
+    //                                                                    ================
+    // -----------------------------------------------------
+    //                                          Mail Address
+    //                                          ------------
+    public void setFrom(String from, String personal) {
+        doSetFrom(from, personal);
+    }
+
+    public void addTo(String to) {
+        doAddTo(to);
+    }
+
+    public void addTo(String to, String personal) {
+        doAddTo(to, personal);
+    }
+
+    public void addCc(String cc) {
+        doAddCc(cc);
+    }
+
+    public void addCc(String cc, String personal) {
+        doAddCc(cc, personal);
+    }
+
+    public void addBcc(String bcc) {
+        doAddBcc(bcc);
+    }
+
+    public void addBcc(String bcc, String personal) {
+        doAddBcc(bcc, personal);
+    }
+
+    public void addReplyTo(String replyTo) {
+        doAddReplyTo(replyTo);
+    }
+
+    public void addReplyTo(String replyTo, String personal) {
+        doAddReplyTo(replyTo, personal);
+    }
+
+    // -----------------------------------------------------
+    //                                  Application Variable
+    //                                  --------------------
+    /**
+     * Set the value of hostname, used in parameter comment. <br>
+     * Even if empty string, treated as empty plainly. So "IF pmb != null" is false if empty.
+     * @param hostname The parameter value of hostname. (NotNull)
+     */
+    public void setHostname(String hostname) {
+        registerVariable("hostname", hostname);
+    }
+}

+ 1 - 1
src/main/resources/fess_env_crawler.properties

@@ -25,7 +25,7 @@ time.adjust.time.millis = 0
 #                                                      Mail
 #                                                     ------
 # Does it send mock mail? (true: no send actually, logging only)
-mail.send.mock = true
+mail.send.mock = false
 
 # SMTP server settings for main: host:port
 mail.smtp.server.main.host.and.port = localhost:25

+ 1 - 1
src/main/resources/fess_env_suggest.properties

@@ -25,7 +25,7 @@ time.adjust.time.millis = 0
 #                                                      Mail
 #                                                     ------
 # Does it send mock mail? (true: no send actually, logging only)
-mail.send.mock = true
+mail.send.mock = false
 
 # SMTP server settings for main: host:port
 mail.smtp.server.main.host.and.port = localhost:25

+ 1 - 1
src/main/resources/fess_label.properties

@@ -654,4 +654,4 @@ labels.general_menu_system=System
 labels.general_menu_crawler=Crawler
 labels.general_menu_logging=Logging
 labels.general_menu_suggest=Suggest
-
+labels.send_testmail=Send TestMail

+ 1 - 0
src/main/resources/fess_label_en.properties

@@ -654,4 +654,5 @@ labels.general_menu_system=System
 labels.general_menu_crawler=Crawler
 labels.general_menu_logging=Logging
 labels.general_menu_suggest=Suggest
+labels.send_testmail=Send TestMail
 

+ 1 - 0
src/main/resources/fess_label_ja.properties

@@ -644,3 +644,4 @@ labels.general_menu_system = \u30b7\u30b9\u30c6\u30e0
 labels.general_menu_crawler = \u30af\u30ed\u30fc\u30e9
 labels.general_menu_logging = \u30ed\u30ae\u30f3\u30b0
 labels.general_menu_suggest = \u30b5\u30b8\u30a7\u30b9\u30c8
+labels.send_testmail=\u30c6\u30b9\u30c8\u30e1\u30fc\u30eb\u306e\u9001\u4fe1

+ 2 - 0
src/main/resources/fess_message.properties

@@ -109,6 +109,7 @@ errors.blank_password=Password is required.
 errors.invalid_confirm_password=Confirm Password does not match.
 errors.cannot_delete_doc_because_of_running=Crawler is running. The document cannot be deleted.
 errors.failed_to_delete_doc_in_admin=Failed to delete document.
+errors.failed_to_send_testmail=Failed to send the test mail.
 
 errors.invalid_query_unknown=The given query has unknown condition.
 errors.invalid_query_parse_error=The given query is invalid.
@@ -135,6 +136,7 @@ success.upload_synonym_file=Uploaded Synonym file.
 success.upload_kuromoji_file=Uploaded Kuromoji file.
 success.upload_elevate_word=Uploaded Additional Word file.
 success.upload_bad_word=Uploaded Bad Word file.
+success.send_testmail=Sent the test mail.
 
 success.crud_create_crud_table=Created data.
 success.crud_update_crud_table=Updated data.

+ 2 - 0
src/main/resources/fess_message_en.properties

@@ -109,6 +109,7 @@ errors.blank_password=Password is required.
 errors.invalid_confirm_password=Confirm Password does not match.
 errors.cannot_delete_doc_because_of_running=Crawler is running. The document cannot be deleted.
 errors.failed_to_delete_doc_in_admin=Failed to delete document.
+errors.failed_to_send_testmail=Failed to send the test mail.
 
 errors.invalid_query_unknown=The given query has unknown condition.
 errors.invalid_query_parse_error=The given query is invalid.
@@ -135,6 +136,7 @@ success.upload_synonym_file=Uploaded Synonym file.
 success.upload_kuromoji_file=Uploaded Kuromoji file.
 success.upload_elevate_word=Uploaded Additional Word file.
 success.upload_bad_word=Uploaded Bad Word file.
+success.send_testmail=Sent the test mail.
 
 success.crud_create_crud_table=Created data.
 success.crud_update_crud_table=Updated data.

+ 2 - 0
src/main/resources/fess_message_ja.properties

@@ -104,6 +104,7 @@ errors.blank_password = \u30d1\u30b9\u30ef\u30fc\u30c9\u304c\u5fc5\u8981\u306b\u
 errors.invalid_confirm_password = \u30d1\u30b9\u30ef\u30fc\u30c9\u306e\u78ba\u8a8d\u3068\u4e00\u81f4\u3057\u307e\u305b\u3093\u3002
 errors.cannot_delete_doc_because_of_running = \u30af\u30ed\u30fc\u30e9\u304c\u5b9f\u884c\u3055\u308c\u3066\u3044\u307e\u3059\u3002\u6587\u66f8\u304c\u524a\u9664\u3059\u308b\u3053\u3068\u306f\u3067\u304d\u307e\u305b\u3093\u3002
 errors.failed_to_delete_doc_in_admin = \u30c9\u30ad\u30e5\u30e1\u30f3\u30c8\u306e\u524a\u9664\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002
+errors.failed_to_send_testmail=\u30c6\u30b9\u30c8\u30e1\u30fc\u30eb\u306e\u9001\u4fe1\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002
 errors.invalid_query_unknown = \u6307\u5b9a\u3055\u308c\u305f\u30af\u30a8\u30ea\u30fc\u306b\u306f\u672a\u77e5\u306e\u6761\u4ef6\u304c\u3042\u308a\u307e\u3059\u3002
 errors.invalid_query_parse_error = \u4e0e\u3048\u3089\u308c\u305f\u30af\u30a8\u30ea\u30fc\u306f\u7121\u52b9\u3067\u3059\u3002
 errors.invalid_query_sort_value = \u6307\u5b9a\u3055\u308c\u305f\u30bd\u30fc\u30c8 {0} \u304c\u7121\u52b9\u3067\u3059\u3002
@@ -127,6 +128,7 @@ success.upload_synonym_file = \u540c\u7fa9\u8a9e\u30d5\u30a1\u30a4\u30eb\u3092\u
 success.upload_kuromoji_file = Kuromoji\u30d5\u30a1\u30a4\u30eb\u3092\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u3057\u307e\u3057\u305f\u3002
 success.upload_elevate_word = \u8ffd\u52a0\u30ef\u30fc\u30c9\u30d5\u30a1\u30a4\u30eb\u3092\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u3057\u307e\u3057\u305f\u3002
 success.upload_bad_word = \u9664\u5916\u30ef\u30fc\u30c9\u30d5\u30a1\u30a4\u30eb\u3092\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u3057\u307e\u3057\u305f\u3002
+success.send_testmail=\u30c6\u30b9\u30c8\u30e1\u30fc\u30eb\u3092\u9001\u4fe1\u3057\u307e\u3057\u305f\u3002
 success.crud_create_crud_table = \u30c7\u30fc\u30bf\u3092\u4f5c\u6210\u3057\u307e\u3057\u305f\u3002
 success.crud_update_crud_table = \u30c7\u30fc\u30bf\u3092\u66f4\u65b0\u3057\u307e\u3057\u305f\u3002
 success.crud_delete_crud_table = \u30c7\u30fc\u30bf\u3092\u524a\u9664\u3057\u307e\u3057\u305f\u3002

+ 7 - 0
src/main/resources/mail/testmail.dfmail

@@ -0,0 +1,7 @@
+/*
+ [Test Mail]
+*/
+subject: [FESS] Test Mail: /*pmb.hostname*/
+>>>
+This is a test mail from /*pmb.hostname*/
+

+ 8 - 1
src/main/webapp/WEB-INF/view/admin/general/admin_general.jsp

@@ -105,7 +105,14 @@
 												key="labels.notification_to" /></label>
 										<div class="col-sm-9">
 											<la:errors property="notificationTo" />
-											<la:text property="notificationTo" styleClass="form-control" />
+											<div class="input-group">
+												<la:text property="notificationTo" styleClass="form-control" />
+												<span class="input-group-btn">
+													<button type="submit" class="btn btn-default" name="sendmail" value="test">
+														<la:message key="labels.send_testmail" />
+													</button>
+												</span>
+											</div>
 										</div>
 									</div>
 									<%-- Crawler --%>