Sotaro KARASAWA 11 лет назад
Родитель
Сommit
806a559db1
7 измененных файлов с 197 добавлено и 15 удалено
  1. 14 0
      form/admin/mail.js
  2. 1 0
      form/index.js
  3. 83 10
      lib/mailer.js
  4. 6 0
      models/config.js
  5. 47 4
      routes/admin.js
  6. 1 0
      routes/index.js
  7. 45 1
      views/admin/app.html

+ 14 - 0
form/admin/mail.js

@@ -0,0 +1,14 @@
+'use strict';
+
+var form = require('express-form')
+  , field = form.field;
+
+module.exports = form(
+  field('settingForm[mail:from]', 'メールFrom').trim(),
+  field('settingForm[mail:smtpHost]', 'SMTPホスト').trim(),
+  field('settingForm[mail:smtpPort]', 'SMTPポート').trim().toInt(),
+  field('settingForm[mail:smtpUser]', 'SMTPユーザー').trim(),
+  field('settingForm[mail:smtpPassword]', 'SMTPパスワード').trim()
+);
+
+

+ 1 - 0
form/index.js

@@ -8,6 +8,7 @@ exports.me = {
 exports.admin = {
   app: require('./admin/app'),
   sec: require('./admin/sec'),
+  mail: require('./admin/mail'),
   aws: require('./admin/aws'),
   google: require('./admin/google'),
   fb: require('./admin/fb'),

+ 83 - 10
lib/mailer.js

@@ -12,16 +12,70 @@ module.exports = function(app) {
     , mailer = {}
     ;
 
-  function initialize() {
-    // SMTP 設定がある場合はそれを優先
-    //if config.crowi
 
-    // AWS 設定がある場合はSESを設定
+  function createSmtpClient(option)
+  {
+    var client;
+
+    debug('createSmtpClient option', option);
+    if (!option) {
+      option = {
+        host: config.crowi['mail:smtpHost'],
+        port: config.crowi['mail:smtpPort'],
+        auth: {
+          user: config.crowi['mail:smtpUser'],
+          pass: config.crowi['mail:smtpPassword']
+        }
+      };
+      if (option.port === 465) {
+        option.secure = true;
+      }
+    }
+
+    client = nodemailer.createTransport(option);
+    return client;
+  }
+
+  function createSESClient(option)
+  {
+    var client;
+
+    if (!option) {
+      option = {
+        accessKeyId: config.crowi['aws:accessKeyId'],
+        secretAccessKey: config.crowi['aws:secretAccessKey']
+      };
+    }
+
     var ses = require('nodemailer-ses-transport');
-    var transporter = nodemailer.createTransport(ses({
-        accessKeyId: 'AWSACCESSKEY',
-        secretAccessKey: 'AWS/Secret/key'
-    }));
+    var client = nodemailer.createTransport(ses(option));
+
+    return client;
+  }
+
+  function initialize() {
+    if (!config.crowi['mail.from']) {
+      mailer = undefined;
+      return;
+    }
+
+    if (config.crowi['mail:smtpUser']
+        && config.crowi['mail:smtpPassword']
+        && config.crowi['mail:smtpHost']
+        && config.crowi['mail:smtpPort']
+      ) {
+      // SMTP 設定がある場合はそれを優先
+      mailer = createSmtpClient();
+
+    } else if (config.crowi['aws:accessKeyId'] && config.crowi['aws:secretAccessKey']) {
+      // AWS 設定がある場合はSESを設定
+      mailer = createSESClient();
+    } else {
+      mailer = undefined;
+    }
+
+    mailConfig.from = config.crowi['mail.from'];
+    mailConfig.subject = config.crowi['app:title'] + 'からのメール';
   }
 
   function setupMailConfig (overrideConfig) {
@@ -30,13 +84,32 @@ module.exports = function(app) {
       ;
     mc = mailConfig;
 
-    mc.from = c.from || mailConfig.from;
+    mc.to      = c.to;
+    mc.to      = 'Sotaro <sotarok@crocos.co.jp>'; // for test
+    mc.from    = c.from || mailConfig.from;
+    mc.from    = 'Crowi <reg@sotaro-k.com>'; // for test
+    mc.text    = c.text;
     mc.subject = c.subject || mailConfig.subject;
 
     return mc;
   }
 
+  function send(config, callback) {
+    if (mailer) {
+      mailer.sendMail(setupMailConfig(config));
+    } else {
+      debug('Mailer is not completed to set up. Please set up SMTP or AWS setting.');
+      callback(new Error('Mailer is not completed to set up. Please set up SMTP or AWS setting.'), null);
+    }
+  }
+
 
   initialize();
-  return mailer;
+
+  return {
+    createSmtpClient: createSmtpClient,
+    createSESClient: createSESClient,
+    mailer: mailer,
+    send: send,
+  };
 };

+ 6 - 0
models/config.js

@@ -30,6 +30,12 @@ module.exports = function(app) {
       'aws:accessKeyId'     : '',
       'aws:secretAccessKey' : '',
 
+      'mail:from'         : '',
+      'mail:smtpHost'     : '',
+      'mail:smtpPort'     : '',
+      'mail:smtpUser'     : '',
+      'mail:smtpPassword' : '',
+
       'searcher:url': '',
 
       'google:clientId'     : '',

+ 47 - 4
routes/admin.js

@@ -161,15 +161,58 @@ module.exports = function(app) {
 
     if (req.form.isValid) {
       debug('form content', form);
-      Config.updateNamespaceByArray('crowi', form, function(err, config) {
-        Config.updateConfigCache('crowi', config)
-        return res.json({status: true});
-      });
+
+      // mail setting ならここで validation
+      if (form['mail:from']) {
+        validateMailSetting(req, form, function(err, data) {
+          if (err) {
+            req.form.errors.push('SMTPを利用したテストメール送信に失敗しました。設定をみなおしてください。');
+            return res.json({status: false, message: req.form.errors.join('\n')});
+          }
+
+          return saveSetting(req, res, form);
+        });
+      } else {
+        return saveSetting(req, res, form);
+      }
     } else {
       return res.json({status: false, message: req.form.errors.join('\n')});
     }
   };
 
+  function saveSetting(req, res, form)
+  {
+    Config.updateNamespaceByArray('crowi', form, function(err, config) {
+      Config.updateConfigCache('crowi', config)
+      return res.json({status: true});
+    });
+  }
+
+  function validateMailSetting(req, form, callback)
+  {
+    var mailer = app.set('mailer');
+    var option = {
+      host: form['mail:smtpHost'],
+      port: form['mail:smtpPort'],
+      auth: {
+        user: form['mail:smtpUser'],
+        pass: form['mail:smtpPassword'],
+      }
+    };
+    if (option.port === 465) {
+      option.secure = true;
+    }
+
+    var smtpClient = mailer.createSmtpClient(option);
+    debug('mailer setup for validate SMTP setting', smtpClient);
+
+    smtpClient.sendMail({
+      to: req.user.email,
+      subject: 'Wiki管理設定のアップデートによるメール通知',
+      text: 'このメールのWikiSMTPメール送信設定のアップデートにより送信されています。'
+    }, callback);
+  }
+
 
   return actions;
 };

+ 1 - 0
routes/index.js

@@ -30,6 +30,7 @@ module.exports = function(app) {
   app.get('/admin/app'                  , middleware.loginRequired(app) , middleware.adminRequired() , admin.app.index);
   app.post('/_api/admin/settings/app'   , middleware.loginRequired(app) , middleware.adminRequired() , form.admin.app, admin.api.appSetting);
   app.post('/_api/admin/settings/sec'   , middleware.loginRequired(app) , middleware.adminRequired() , form.admin.sec, admin.api.appSetting);
+  app.post('/_api/admin/settings/mail'  , middleware.loginRequired(app) , middleware.adminRequired() , form.admin.mail, admin.api.appSetting);
   app.post('/_api/admin/settings/aws'   , middleware.loginRequired(app) , middleware.adminRequired() , form.admin.aws, admin.api.appSetting);
   app.post('/_api/admin/settings/google', middleware.loginRequired(app) , middleware.adminRequired() , form.admin.google, admin.api.appSetting);
   app.post('/_api/admin/settings/fb'    , middleware.loginRequired(app) , middleware.adminRequired() , form.admin.fb

+ 45 - 1
views/admin/app.html

@@ -115,6 +115,50 @@
       </fieldset>
       </form>
 
+      <form action="/_api/admin/settings/mail" method="post" class="form-horizontal" id="mailSettingForm" role="form">
+      <fieldset>
+      <legend>メールの設定</legend>
+      <p class="well">SMTPの設定がされている場合、それが利用されます。SMTP設定がなく、AWSの設定がある場合、SESでの送信を試みます。<br>どちらの設定もない場合、メールは送信されません。</p>
+
+        <div class="form-group">
+          <label for="settingForm[mail.from]" class="col-xs-3 control-label">Fromアドレス</label>
+          <div class="col-xs-6">
+            <input class="form-control" type="text" name="settingForm[mail:from]" placeholder="例: mail@crowi.wiki" value="{{ settingForm['mail:from'] }}">
+          </div>
+        </div>
+
+        <div class="form-group">
+          <label class="col-xs-3 control-label">SMTP設定</label>
+          <div class="col-xs-4">
+            <label for="">ホスト</label>
+            <input class="form-control" type="text" name="settingForm[mail:smtpHost]"   value="{{ settingForm['mail:smtpHost']|default('') }}">
+          </div>
+          <div class="col-xs-2">
+            <label for="">ポート</label>
+            <input class="form-control" type="text" name="settingForm[mail:smtpPort]" value="{{ settingForm['mail:smtpPort']|default('') }}">
+          </div>
+        </div>
+
+        <div class="form-group">
+          <div class="col-xs-3 col-xs-offset-3">
+            <label for="">ユーザー</label>
+            <input class="form-control" type="text" name="settingForm[mail:smtpUser]"   value="{{ settingForm['mail:smtpUser']|default('') }}">
+          </div>
+          <div class="col-xs-3">
+            <label for="">パスワード</label>
+            <input class="form-control" type="password" name="settingForm[mail:smtpPassword]" value="{{ settingForm['mail:smtpPassword']|default('') }}">
+          </div>
+        </div>
+
+        <div class="form-group">
+          <div class="col-xs-offset-3 col-xs-6">
+            <button type="submit" class="btn btn-primary">更新</button>
+          </div>
+        </div>
+
+      </fieldset>
+      </form>
+
       <form action="/_api/admin/settings/aws" method="post" class="form-horizontal" id="awsSettingForm" role="form">
       <fieldset>
       <legend>AWS設定</legend>
@@ -223,7 +267,7 @@
   <script>
     $(function()
     {
-      $('#appSettingForm, #secSettingForm, #awsSettingForm, #googleSettingForm, #fbSettingForm').each(function() {
+      $('#appSettingForm, #secSettingForm, #mailSettingForm, #awsSettingForm, #googleSettingForm, #fbSettingForm').each(function() {
         $(this).submit(function()
         {
           function showMessage(formId, msg, status) {