Implement a way to get/set the nodemailer object (has an entries for contact, feedbac...
authorNick Downing <nick@ndcode.org>
Sun, 23 Jan 2022 02:47:46 +0000 (13:47 +1100)
committerNick Downing <nick@ndcode.org>
Sun, 23 Jan 2022 03:03:17 +0000 (14:03 +1100)
13 files changed:
_config/n.sh
_config/nodemailer.json [new file with mode: 0644]
_config/nodemailer_contact.json [deleted file]
_config/nodemailer_feedback.json [deleted file]
_config/nodemailer_noreply.json [deleted file]
_config/site.jst
api/account/password_reset.json.jst
api/account/sign_up/send_email_verification_link.json.jst
api/contact/send_enquiry.json.jst
api/feedback.json.jst
api/nodemailer/get.json.jst [new file with mode: 0644]
api/nodemailer/set.json.jst [new file with mode: 0644]
package.json

index 197f13a..5bcb282 100755 (executable)
@@ -1,2 +1,3 @@
 #!/bin/sh
 ./set.mjs /api/globals/set.json <globals.json
+./set.mjs /api/nodemailer/set.json <nodemailer.json
diff --git a/_config/nodemailer.json b/_config/nodemailer.json
new file mode 100644 (file)
index 0000000..ca93c17
--- /dev/null
@@ -0,0 +1,32 @@
+{
+  "contact": {
+    "host": "mail.ndcode.org",
+    "port": 587,
+    "secure": false,
+    "auth": {
+      "user": "contact@ndcode.org",
+      "pass": "XXXContact12"
+    },
+    "requireTLS": true
+  },
+  "feedback": {
+    "host": "mail.ndcode.org",
+    "port": 587,
+    "secure": false,
+    "auth": {
+      "user": "feedback@ndcode.org",
+      "pass": "XXXFeedback12"
+    },
+    "requireTLS": true
+  },
+  "noreply": {
+    "host": "mail.ndcode.org",
+    "port": 587,
+    "secure": false,
+    "auth": {
+      "user": "noreply@ndcode.org",
+      "pass": "XXXNoreply12"
+    },
+    "requireTLS": true
+  }
+}
diff --git a/_config/nodemailer_contact.json b/_config/nodemailer_contact.json
deleted file mode 100644 (file)
index f98e2ec..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-  "host": "mail.ndcode.org",
-  "port": 587,
-  "secure": false,
-  "auth": {
-    "user": "contact@ndcode.org",
-    "pass": ",b4UtuaEj6"
-  },
-  "requireTLS": true
-}
diff --git a/_config/nodemailer_feedback.json b/_config/nodemailer_feedback.json
deleted file mode 100644 (file)
index 8104cb2..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-  "host": "mail.ndcode.org",
-  "port": 587,
-  "secure": false,
-  "auth": {
-    "user": "feedback@ndcode.org",
-    "pass": "{22fPwun4m"
-  },
-  "requireTLS": true
-}
diff --git a/_config/nodemailer_noreply.json b/_config/nodemailer_noreply.json
deleted file mode 100644 (file)
index 7012e82..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-  "host": "mail.ndcode.org",
-  "port": 587,
-  "secure": false,
-  "auth": {
-    "user": "noreply@ndcode.org",
-    "pass": "NM7ffn(4pT"
-  },
-  "requireTLS": true
-}
index 4caff7d..39cd99f 100644 (file)
@@ -1,6 +1,6 @@
 let assert = require('assert')
 let logjson = (await import('@ndcode/logjson')).default
-let NodeMailerCache = require('@ndcode/nodemailer_cache')
+//let NodeMailerCache = require('@ndcode/nodemailer_cache')
 let XDate = require('xdate')
 let ZettairCache = require('@ndcode/zettair_cache')
 
@@ -29,11 +29,11 @@ return async (resources, root, prev_site) => {
         }
       )
 
-      assert(this.nodemailer_cache === undefined)
-      this.nodemailer_cache = await this.resources.ref(
-        'nodemailer_cache',
-        async () => new NodeMailerCache(true)
-      )
+      //assert(this.nodemailer_cache === undefined)
+      //this.nodemailer_cache = await this.resources.ref(
+      //  'nodemailer_cache',
+      //  async () => new NodeMailerCache(true)
+      //)
 
       assert(this.zettair_cache === undefined)
       this.zettair_cache = await this.resources.ref(
@@ -52,8 +52,8 @@ return async (resources, root, prev_site) => {
       assert(this.database !== undefined)
       await this.resources.unref('database')
 
-      assert(this.nodemailer_cache !== undefined)
-      await this.resources.unref('nodemailer_cache')
+      //assert(this.nodemailer_cache !== undefined)
+      //await this.resources.unref('nodemailer_cache')
 
       assert(this.zettair_cache !== undefined)
       await this.resources.unref('zettair_cache')
@@ -80,17 +80,17 @@ return async (resources, root, prev_site) => {
         this.database_date = new_database_date
       }
 
-      assert(this.nodemailer_cache !== undefined)
-      this.nodemailer_cache.kick()
+      //assert(this.nodemailer_cache !== undefined)
+      //this.nodemailer_cache.kick()
 
       assert(this.zettair_cache !== undefined)
       this.zettair_cache.kick()
     }
 
-    // retrieves a particular email account (as a nodemailer transport)
-    get_nodemailer(pathname) {
-      return /*await*/ this.nodemailer_cache.get(this.root + pathname)
-    }
+    //// retrieves a particular email account (as a nodemailer transport)
+    //get_nodemailer(pathname) {
+    //  return /*await*/ this.nodemailer_cache.get(this.root + pathname)
+    //}
 
     // retrieves a particular search index (node.js wrapper of a zettair object)
     get_zettair(pathname) {
index ff6aed9..f652800 100644 (file)
@@ -1,10 +1,8 @@
 let crypto = require('crypto')
+let nodemailer = require('nodemailer')
 let XDate = require('xdate')
 
 return async env => {
-  let nodemailer_noreply = await env.site.get_nodemailer(
-    '/_config/nodemailer_noreply.json'
-  )
   let post_request = await _require('/_lib/post_request.jst')
   let session_cookie = await _require('/_lib/session_cookie.jst')
   let Problem = await _require('/_lib/Problem.jst')
@@ -25,6 +23,9 @@ return async env => {
         )
 
       let transaction = await env.site.database.Transaction()
+      let link_code
+      let nodemailer_noreply, noreply_from, noreply_signature
+      let given_names, family_name
       try {
         // initialize env.session_key, set cookie in env.response
         await session_cookie(env, transaction)
@@ -41,7 +42,7 @@ return async env => {
             421
           )
 
-        let link_code = crypto.randomBytes(16).toString('hex')
+        link_code = crypto.randomBytes(16).toString('hex')
         let expires = new XDate()
         expires.addDays(1)
         account.set_json(
@@ -49,22 +50,33 @@ return async env => {
           {password, link_code, expires: expires.getTime()}
         )
 
-        let globals = await (await transaction.get({})).get('globals')
-        let site_url = await globals.get_json('site_url')
-        let noreply_from = await globals.get_json('noreply_from')
-        let noreply_signature = await globals.get_json('noreply_signature')
+        let root = await transaction.get({})
+        nodemailer_noreply = nodemailer.createTransport(
+          await (await root.get('nodemailer')).get_json('noreply')
+        )
+        let globals = await root.get('globals')
+        site_url = await globals.get_json('site_url')
+        noreply_from = await globals.get_json('noreply_from')
+        noreply_signature = await globals.get_json('noreply_signature')
+
+        given_names = await account.get_json('given_names', '')
+        family_name = await account.get_json('family_name', '')
 
-        let given_names = await account.get_json('given_names', '')
-        let family_name = await account.get_json('family_name', '')
-        let name =
-          family_name.length ? `${given_names} ${family_name}` : given_names
+        await transaction.commit()
+      }
+      catch (error) {
+        transaction.rollback()
+        throw error
+      }
 
-        await nodemailer_noreply.sendMail(
-          {
-            from: noreply_from,
-            to: `${name} <${email}>`,
-            subject: 'Password reset',
-            text: `Dear ${given_names},
+      let name =
+        family_name.length ? `${given_names} ${family_name}` : given_names
+      await nodemailer_noreply.sendMail(
+        {
+          from: noreply_from,
+          to: `${name} <${email}>`,
+          subject: 'Password reset',
+          text: `Dear ${given_names},
 
 We have received a request to reset the account password for your email address.
 
@@ -76,15 +88,8 @@ The link is valid for 24 hours.
 Thanks,
 ${noreply_signature}
 `
-          }
-        )
-
-        await transaction.commit()
-      }
-      catch (error) {
-        transaction.rollback()
-        throw error
-      }
+        }
+      )
     }
   )
 }
index c682c2c..ac64ba5 100644 (file)
@@ -1,10 +1,8 @@
 let crypto = require('crypto')
+let nodemailer = require('nodemailer')
 let XDate = require('xdate')
 
 return async env => {
-  let nodemailer_noreply = await env.site.get_nodemailer(
-    '/_config/nodemailer_noreply.json'
-  )
   let post_request = await _require('/_lib/post_request.jst')
   let session_cookie = await _require('/_lib/session_cookie.jst')
   let Problem = await _require('/_lib/Problem.jst')
@@ -24,6 +22,9 @@ return async env => {
         )
 
       let transaction = await env.site.database.Transaction()
+      let link_code
+      let nodemailer_noreply, site_url, noreply_from, noreply_signature
+      let given_names, family_name
       try {
         // initialize env.session_key, set cookie in env.response
         await session_cookie(env, transaction)
@@ -47,7 +48,7 @@ return async env => {
             422
           )
 
-        let link_code = crypto.randomBytes(16).toString('hex')
+        link_code = crypto.randomBytes(16).toString('hex')
         let expires = new XDate()
         expires.addDays(1)
         account.set_json(
@@ -55,22 +56,33 @@ return async env => {
           {link_code, expires: expires.getTime()}
         )
 
-        let globals = await (await transaction.get({})).get('globals')
-        let site_url = await globals.get_json('site_url')
-        let noreply_from = await globals.get_json('noreply_from')
-        let noreply_signature = await globals.get_json('noreply_signature')
+        let root = await transaction.get({})
+        nodemailer_noreply = nodemailer.createTransport(
+          await (await root.get('nodemailer')).get_json('noreply')
+        )
+        let globals = await root.get('globals')
+        site_url = await globals.get_json('site_url')
+        noreply_from = await globals.get_json('noreply_from')
+        noreply_signature = await globals.get_json('noreply_signature')
+
+        given_names = await account.get_json('given_names', '')
+        family_name = await account.get_json('family_name', '')
 
-        let given_names = await account.get_json('given_names', '')
-        let family_name = await account.get_json('family_name', '')
-        let name =
-          family_name.length ? `${given_names} ${family_name}` : given_names
+        await transaction.commit()
+      }
+      catch (error) {
+        transaction.rollback()
+        throw error
+      }
 
-        await nodemailer_noreply.sendMail(
-          {
-            from: noreply_from,
-            to: `${name} <${email}>`,
-            subject: 'Email address verification',
-            text: `Dear ${given_names},
+      let name =
+        family_name.length ? `${given_names} ${family_name}` : given_names
+      await nodemailer_noreply.sendMail(
+        {
+          from: noreply_from,
+          to: `${name} <${email}>`,
+          subject: 'Email address verification',
+          text: `Dear ${given_names},
 
 We have received a request to sign up using your email address.
 
@@ -82,15 +94,8 @@ The link is valid for 24 hours.
 Thanks,
 ${noreply_signature}
 `
-          }
-        )
-
-        await transaction.commit()
-      }
-      catch (error) {
-        transaction.rollback()
-        throw error
-      }
+        }
+      )
     }
   )
 }
index 04ac3b0..f1e5598 100644 (file)
@@ -1,10 +1,7 @@
-let crypto = require('crypto')
+let nodemailer = require('nodemailer')
 let XDate = require('xdate')
 
 return async env => {
-  let nodemailer_contact = await env.site.get_nodemailer(
-    '/_config/nodemailer_contact.json'
-  )
   let post_request = await _require('/_lib/post_request.jst')
   let session_cookie = await _require('/_lib/session_cookie.jst')
   let Problem = await _require('/_lib/Problem.jst')
@@ -34,12 +31,16 @@ return async env => {
         )
 
       let transaction = await env.site.database.Transaction()
-      let contact_from, contact_to
+      let nodemailer_contact, contact_from, contact_to
       try {
         // initialize env.session_key, set cookie in env.response
         session_cookie(env, transaction)
 
-        let globals = await (await transaction.get({})).get('globals')
+        let root = await transaction.get({})
+        nodemailer_contact = nodemailer.createTransport(
+          await (await root.get('nodemailer')).get_json('contact')
+        )
+        let globals = await root.get('globals')
         contact_from = await globals.get_json('contact_from')
         contact_to = await globals.get_json('contact_to')
 
index 8d6f201..7cc4feb 100644 (file)
@@ -1,9 +1,7 @@
+let nodemailer = require('nodemailer')
 let XDate = require('xdate')
 
 return async env => {
-  let nodemailer_feedback = await env.site.get_nodemailer(
-    '/_config/nodemailer_feedback.json'
-  )
   let post_request = await _require('/_lib/post_request.jst')
   let session_cookie = await _require('/_lib/session_cookie.jst')
 
@@ -23,12 +21,16 @@ return async env => {
         )
 
       let transaction = await env.site.database.Transaction()
-      let feedback_from, feedback_to
+      let nodemailer_feedback, feedback_from, feedback_to
       try {
         // initialize env.session_key, set cookie in env.response
         await session_cookie(env, transaction)
 
-        let globals = await (await transaction.get({})).get('globals')
+        let root = await transaction.get({})
+        nodemailer_feedback = nodemailer.createTransport(
+          await (await root.get('nodemailer')).get_json('feedback')
+        )
+        let globals = await root.get('globals')
         feedback_from = await globals.get_json('feedback_from')
         feedback_to = await globals.get_json('feedback_to')
 
diff --git a/api/nodemailer/get.json.jst b/api/nodemailer/get.json.jst
new file mode 100644 (file)
index 0000000..6fcce8c
--- /dev/null
@@ -0,0 +1,38 @@
+let XDate = require('xdate')
+
+return async env => {
+  let post_request = await _require('/_lib/post_request.jst')
+  let session_cookie = await _require('/_lib/session_cookie.jst')
+  let Problem = await _require('/_lib/Problem.jst')
+
+  await post_request(
+    // env
+    env,
+    // handler
+    async () => {
+      let transaction = await env.site.database.Transaction()
+      try {
+        // initialize env.session_key, set cookie in env.response
+        await session_cookie(env, transaction)
+        if (env.signed_in_as === null)
+          throw new Problem('Unauthorized', 'Please sign in first.', 401)
+
+        let root = await transaction.get({})
+        let account = await (
+          await root.get('accounts', {})
+        ).get(env.signed_in_as)
+        if (!await account.get_json('administrator'))
+          throw new Problem('Unauthorized', 'Not administrator.', 401)
+
+        nodemailer = await root.get_json('nodemailer', {})
+
+        await transaction.commit()
+        return nodemailer
+      }
+      catch (error) {
+        transaction.rollback()
+        throw error
+      }
+    }
+  )
+}
diff --git a/api/nodemailer/set.json.jst b/api/nodemailer/set.json.jst
new file mode 100644 (file)
index 0000000..101a7fc
--- /dev/null
@@ -0,0 +1,39 @@
+let XDate = require('xdate')
+
+return async env => {
+  let post_request = await _require('/_lib/post_request.jst')
+  let session_cookie = await _require('/_lib/session_cookie.jst')
+  let Problem = await _require('/_lib/Problem.jst')
+
+  await post_request(
+    // env
+    env,
+    // handler
+    async nodemailer => {
+      // do not bother trying to coerce and/or validate
+      // too complex and nested (do it when we have an automated routine)
+
+      let transaction = await env.site.database.Transaction()
+      try {
+        // initialize env.session_key, set cookie in env.response
+        await session_cookie(env, transaction)
+        if (env.signed_in_as === null)
+          throw new Problem('Unauthorized', 'Please sign in first.', 401)
+
+        let root = await transaction.get({})
+        let account = await (
+          await root.get('accounts', {})
+        ).get(env.signed_in_as)
+        if (!await account.get_json('administrator'))
+          throw new Problem('Unauthorized', 'Not administrator.', 401)
+
+        root.set_json('nodemailer', nodemailer)
+        await transaction.commit()
+      }
+      catch (error) {
+        transaction.rollback()
+        throw error
+      }
+    }
+  )
+}
index 0c3a724..f31e278 100644 (file)
@@ -5,10 +5,10 @@
   "directories": {},
   "dependencies": {
     "@ndcode/logjson": "^0.1.0",
-    "@ndcode/nodemailer_cache": "^0.1.0",
     "@ndcode/zettair_cache": "^0.1.0",
     "captchagen": "^1.2.0",
     "cookie": "^0.3.1",
+    "nodemailer": "^6.7.2",
     "querystring": "^0.2.0",
     "stream-buffers": "^3.0.2",
     "xdate": "^0.8.2"