JSON lookup
authorJeremy Harris <jgh146exb@wizmail.org>
Sat, 9 Feb 2019 16:48:08 +0000 (16:48 +0000)
committerJeremy Harris <jgh146exb@wizmail.org>
Mon, 11 Feb 2019 00:15:39 +0000 (00:15 +0000)
(cherry picked from commits 854bd65fa711b31159ac19cb5e2f149669c6e06f6db8b72c86)

16 files changed:
doc/doc-docbook/spec.xfpt
doc/doc-txt/NewStuff
src/scripts/MakeLinks
src/scripts/lookups-Makefile
src/src/EDITME
src/src/config.h.defaults
src/src/drtables.c
src/src/exim.c
src/src/lookups/Makefile
src/src/lookups/json.c [new file with mode: 0644]
src/src/macro_predef.c
test/aux-fixed/policy.json [new file with mode: 0644]
test/confs/2750 [new file with mode: 0644]
test/scripts/2750-json/2750 [new file with mode: 0644]
test/scripts/2750-json/REQUIRES [new file with mode: 0644]
test/stdout/2750 [new file with mode: 0644]

index 958e7caf6a5b15a4f0b9a0f1dd5e3c12d19f61fa..46cab7c58fa68736261537b69a384c90bf836b00 100644 (file)
@@ -6742,6 +6742,24 @@ lookup types support only literal keys.
 the implicit key is the host's IP address rather than its name (see section
 &<<SECThoslispatsikey>>&).
 .next
+.new
+.cindex lookup json
+.cindex json "lookup type"
+.cindex JSON expansions
+&(json)&: The given file is a text file with a JSON structure.
+An element of the structure is extracted, defined by the search key.
+The key is a list of subelement selectors
+(colon-separated by default but changeable in the usual way)
+which are applied in turn to select smaller and smaller portions
+of the JSON structure.
+If a selector is numeric, it must apply to a JSON array; the (zero-based)
+nunbered array element is selected.
+Otherwise it must apply to a JSON object; the named element is selected.
+The final resulting object can be a simple JSOM type or a JSON object
+or array; for the latter two a string-representation os the JSON
+is returned.
+.wen
+.next
 .cindex "linear search"
 .cindex "lookup" "lsearch"
 .cindex "lsearch lookup type"
index 07577ec11d934959bb5f35eeacc21d1f0e4595c7..8dc3648f5a7c9fa368d369265fcfcba69355c3c7 100644 (file)
@@ -11,6 +11,7 @@ Version 4.93
 
  1. An "external" authenticator, per RFC 4422 Appendix A.
 
+ 2. A JSON lookup type.
 
 Version 4.92
 --------------
index f69bde437d59645d570e8d5f42cfc16a83c8844b..b717367978f5eedf602852e00c6c54bc2e465cb6 100755 (executable)
@@ -30,7 +30,7 @@ echo ">>> Creating links to source files..."
 mkdir lookups
 cd lookups
 # Makefile is generated
-for f in README cdb.c dbmdb.c dnsdb.c dsearch.c ibase.c ldap.h ldap.c \
+for f in README cdb.c dbmdb.c dnsdb.c dsearch.c ibase.c json.c ldap.h ldap.c \
   lmdb.c lsearch.c mysql.c redis.c nis.c nisplus.c oracle.c passwd.c \
   pgsql.c spf.c sqlite.c testdb.c whoson.c \
   lf_functions.h lf_check_file.c lf_quote.c lf_sqlperform.c
index db2d184a731a6995e89ee0c281893a41f5c8da6f..498184ff6eea9f73d03c5f45586d120a22428559 100755 (executable)
@@ -160,7 +160,7 @@ exec > "$target"
 sed -n "1,/$tag_marker/p" < "$input"
 
 for name_mod in \
-    CDB DBM:dbmdb DNSDB DSEARCH IBASE LSEARCH MYSQL NIS NISPLUS ORACLE \
+    CDB DBM:dbmdb DNSDB DSEARCH IBASE JSON LSEARCH MYSQL NIS NISPLUS ORACLE \
     PASSWD PGSQL REDIS SQLITE TESTDB WHOSON
 do
   emit_module_rule $name_mod
index 15360db9acd39eed61910e84ba54c3164ce78459..b2c27dafe9018e177f631b8f94eb65559c7a6548 100644 (file)
@@ -309,6 +309,7 @@ LOOKUP_DNSDB=yes
 # LOOKUP_CDB=yes
 # LOOKUP_DSEARCH=yes
 # LOOKUP_IBASE=yes
+# LOOKUP_JSON=yes
 # LOOKUP_LDAP=yes
 # LOOKUP_MYSQL=yes
 # LOOKUP_MYSQL_PC=mariadb
@@ -376,7 +377,7 @@ PCRE_CONFIG=yes
 # don't need to set LOOKUP_INCLUDE if the relevant directories are already
 # specified in INCLUDE. The settings below are just examples; -lpq is for
 # PostgreSQL, -lgds is for Interbase, -lsqlite3 is for SQLite, -lhiredis
-# is for Redis.
+# is for Redis, -ljansson for JSON.
 #
 # You do not need to use this for any lookup information added via pkg-config.
 
index 74ec3f4df68ecfb46af269d357f240793dab8960..55688295de20f9dc87dd70faa5b07a53c11911c8 100644 (file)
@@ -93,6 +93,7 @@ Do not put spaces between # and the 'define'.
 #define LOOKUP_DNSDB
 #define LOOKUP_DSEARCH
 #define LOOKUP_IBASE
+#define LOOKUP_JSON
 #define LOOKUP_LDAP
 #define LOOKUP_LSEARCH
 #define LOOKUP_MYSQL
index 54d03edab455878717585275f49e5cf267924883..b7024297d962e38bcccfe02c9ef8cbe7b9eadb25 100644 (file)
@@ -564,6 +564,9 @@ extern lookup_module_info dsearch_lookup_module_info;
 #if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
 extern lookup_module_info ibase_lookup_module_info;
 #endif
+#if defined(LOOKUP_JSON)
+extern lookup_module_info json_lookup_module_info;
+#endif
 #if defined(LOOKUP_LDAP)
 extern lookup_module_info ldap_lookup_module_info;
 #endif
@@ -649,6 +652,10 @@ init_lookup_list(void)
   addlookupmodule(NULL, &ldap_lookup_module_info);
 #endif
 
+#ifdef LOOKUP_JSON
+  addlookupmodule(NULL, &json_lookup_module_info);
+#endif
+
 #if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
   addlookupmodule(NULL, &lsearch_lookup_module_info);
 #endif
index d693c9f98828c69596b542829aba069c8a38498d..8e700f7114d151b20003782f75581c10d4e86c1a 100644 (file)
@@ -930,6 +930,9 @@ fprintf(fp, "Lookups (built-in):");
 #if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
   fprintf(fp, " ibase");
 #endif
+#if defined(LOOKUP_JSON) && LOOKUP_JSON!=2
+  fprintf(fp, " json");
+#endif
 #if defined(LOOKUP_LDAP) && LOOKUP_LDAP!=2
   fprintf(fp, " ldap ldapdn ldapm");
 #endif
index 7c9700690580e3e878ecbb34235a2db41e739ebf..01910d542ed5ac2f0d999fea283d995a6edc675c 100644 (file)
@@ -35,6 +35,7 @@ dsearch.o:       $(PHDRS) dsearch.c
 ibase.o:         $(PHDRS) ibase.c
 ldap.o:          $(PHDRS) ldap.c
 lmdb.o:          $(PHDRS) lmdb.c
+json.o:          $(PHDRS) json.c
 lsearch.o:       $(PHDRS) lsearch.c
 mysql.o:         $(PHDRS) mysql.c
 nis.o:           $(PHDRS) nis.c
@@ -53,6 +54,7 @@ dbmdb.so:         $(PHDRS) dbmdb.c
 dnsdb.so:         $(PHDRS) dnsdb.c
 dsearch.so:       $(PHDRS) dsearch.c
 ibase.so:         $(PHDRS) ibase.c
+json.so:          $(PHDRS) json.c
 ldap.so:          $(PHDRS) ldap.c
 lmdb.so:          $(PHDRS) lmdb.c
 lsearch.so:       $(PHDRS) lsearch.c
diff --git a/src/src/lookups/json.c b/src/src/lookups/json.c
new file mode 100644 (file)
index 0000000..0b28b73
--- /dev/null
@@ -0,0 +1,192 @@
+/*************************************************
+*     Exim - an Internet mail transport agent    *
+*************************************************/
+
+/* Copyright (c) Jeremy Harris 2019 */
+/* See the file NOTICE for conditions of use and distribution. */
+
+#include "../exim.h"
+#include "lf_functions.h"
+#include <jansson.h>
+
+
+
+/* All use of allocations will be done against the POOL_SEARCH memory,
+which is freed once by search_tidyup(). Make the free call a dummy.
+This burns some 300kB in handling a 37kB JSON file, for the benefit of
+a fast free.  The alternative of staying with malloc is nearly as bad,
+eyeballing the activity there are 20% the number of free vs. alloc
+calls (before the big bunch at the end). */
+
+static void *
+json_malloc(size_t nbytes)
+{
+void * p = store_get((int)nbytes);
+/* debug_printf("%s %d: %p\n", __FUNCTION__, (int)nbytes, p); */
+return p;
+}
+static void
+json_free(void * p)
+{
+/* debug_printf("%s: %p\n", __FUNCTION__, p); */
+}
+
+/*************************************************
+*              Open entry point                  *
+*************************************************/
+
+/* See local README for interface description */
+
+static void *
+json_open(uschar *filename, uschar **errmsg)
+{
+FILE * f;
+
+json_set_alloc_funcs(json_malloc, json_free);
+
+if (!(f = Ufopen(filename, "rb")))
+  {
+  int save_errno = errno;
+  *errmsg = string_open_failed(errno, "%s for json search", filename);
+  errno = save_errno;
+  return NULL;
+  }
+return f;
+}
+
+
+
+/*************************************************
+*             Check entry point                  *
+*************************************************/
+
+static BOOL
+json_check(void *handle, uschar *filename, int modemask, uid_t *owners,
+  gid_t *owngroups, uschar **errmsg)
+{
+return lf_check_file(fileno((FILE *)handle), filename, S_IFREG, modemask,
+  owners, owngroups, "json", errmsg) == 0;
+}
+
+
+
+/*************************************************
+*         Find entry point for lsearch           *
+*************************************************/
+
+/* See local README for interface description */
+
+static int
+json_find(void *handle, uschar *filename, const uschar *keystring, int length,
+  uschar **result, uschar **errmsg, uint *do_cache)
+{
+FILE * f = handle;
+json_t * j, * j0;
+json_error_t jerr;
+uschar * key;
+int sep = 0;
+
+length = length;       /* Keep picky compilers happy */
+do_cache = do_cache;   /* Keep picky compilers happy */
+
+rewind(f);
+if (!(j = json_loadf(f, 0, &jerr)))
+  {
+  *errmsg = string_sprintf("json error on open: %.*s\n",
+       JSON_ERROR_TEXT_LENGTH, jerr.text);
+  return FAIL;
+  }
+j0 = j;
+
+for (int k = 1;  (key = string_nextinlist(&keystring, &sep, NULL, 0)); k++)
+  {
+  BOOL numeric = TRUE;
+  for (uschar * s = key; *s; s++) if (!isdigit(*s)) { numeric = FALSE; break; }
+
+  if (!(j = numeric
+       ? json_array_get(j, (size_t) strtoul(CS key, NULL, 10))
+       : json_object_get(j, CCS key)
+     ) )
+    {
+    DEBUG(D_lookup) debug_printf("%s, for key %d: '%s'\n",
+      numeric
+      ? US"bad index, or not json array"
+      : US"no such key, or not json object",
+      k, key);
+    json_decref(j0);
+    return FAIL;
+    }
+  }
+
+switch (json_typeof(j))
+  {
+  case JSON_STRING:
+    *result = string_copyn(CUS json_string_value(j), json_string_length(j));
+    break;
+  case JSON_INTEGER:
+    *result = string_sprintf("%" JSON_INTEGER_FORMAT, json_integer_value(j));
+    break;
+  case JSON_REAL:
+    *result = string_sprintf("%f", json_real_value(j));
+    break;
+  case JSON_TRUE:      *result = US"true";     break;
+  case JSON_FALSE:     *result = US"false";    break;
+  case JSON_NULL:      *result = NULL;         break;
+  default:             *result = US json_dumps(j, 0); break;
+  }
+json_decref(j0);
+return OK;
+}
+
+
+
+/*************************************************
+*              Close entry point                 *
+*************************************************/
+
+/* See local README for interface description */
+
+static void
+json_close(void *handle)
+{
+(void)fclose((FILE *)handle);
+}
+
+
+
+/*************************************************
+*         Version reporting entry point          *
+*************************************************/
+
+/* See local README for interface description. */
+
+#include "../version.h"
+
+void
+json_version_report(FILE *f)
+{
+fprintf(f, "Library version: json: Jansonn version %s\n", JANSSON_VERSION);
+}
+
+
+static lookup_info json_lookup_info = {
+  US"json",                      /* lookup name */
+  lookup_absfile,                /* uses absolute file name */
+  json_open,                  /* open function */
+  json_check,                 /* check function */
+  json_find,                  /* find function */
+  json_close,                 /* close function */
+  NULL,                          /* no tidy function */
+  NULL,                          /* no quoting function */
+  json_version_report         /* version reporting */
+};
+
+
+#ifdef DYNLOOKUP
+#define json_lookup_module_info _lookup_module_info
+#endif
+
+static lookup_info *_lookup_list[] = { &json_lookup_info };
+lookup_module_info json_lookup_module_info = { LOOKUP_MODULE_INFO_MAGIC, _lookup_list, 1 };
+
+/* End of lookups/json.c */
index 84a33282dd0521b1b2d819cc025229cc71b6e3c5..f92671ae2b85db5d96d00dfb37d517fe970bd1b4 100644 (file)
@@ -222,6 +222,9 @@ due to conflicts with other common macros. */
 #ifdef LOOKUP_IBASE
   builtin_macro_create(US"_HAVE_LOOKUP_IBASE");
 #endif
+#ifdef LOOKUP_LDAP
+  builtin_macro_create(US"_HAVE_LOOKUP_JSON");
+#endif
 #ifdef LOOKUP_LDAP
   builtin_macro_create(US"_HAVE_LOOKUP_LDAP");
 #endif
diff --git a/test/aux-fixed/policy.json b/test/aux-fixed/policy.json
new file mode 100644 (file)
index 0000000..8f31ec9
--- /dev/null
@@ -0,0 +1,2008 @@
+{
+  "timestamp": "2019-01-03T10:54:53.971169744-08:00",
+  "expires": "2019-01-17T10:54:53.971169744-08:00",
+  "version": "0.1",
+  "author": "Electronic Frontier Foundation https://eff.org",
+  "policy-aliases": {
+    "google": {
+      "mode": "testing",
+      "mxs": [
+        ".l.google.com"
+      ]
+    },
+    "icloud": {
+      "mode": "testing",
+      "mxs": [
+        ".icloud.com"
+      ]
+    },
+    "outlook": {
+      "mode": "testing",
+      "mxs": [
+        ".outlook.com",
+        "outlook.com"
+      ]
+    },
+    "yahoo": {
+      "mode": "testing",
+      "mxs": [
+        ".yahoodns.net"
+      ]
+    }
+  },
+  "policies": {
+    "aol.com": {
+      "policy-alias": "yahoo"
+    },
+    "comcast.net": {
+      "mode": "testing",
+      "mxs": [
+        ".comcast.net"
+      ]
+    },
+    "eff.org": {
+      "mode": "testing",
+      "mxs": [
+        ".eff.org"
+      ]
+    },
+    "facebook.com": {
+      "mode": "testing",
+      "mxs": [
+        ".facebook.com"
+      ]
+    },
+    "gmail.com": {
+      "policy-alias": "google"
+    },
+    "hotmail.com": {
+      "policy-alias": "outlook"
+    },
+    "icloud.com": {
+      "policy-alias": "icloud"
+    },
+    "live.com": {
+      "policy-alias": "outlook"
+    },
+    "me.com": {
+      "policy-alias": "icloud"
+    },
+    "msn.com": {
+      "policy-alias": "outlook"
+    },
+    "outlook.com": {
+      "policy-alias": "outlook"
+    },
+    "qq.com": {
+      "mode": "testing",
+      "mxs": [
+        ".qq.com"
+      ]
+    },
+    "rocketmail.com": {
+      "policy-alias": "yahoo"
+    },
+    "salesforce.com": {
+      "policy-alias": "google"
+    },
+    "yahoo.com": {
+      "policy-alias": "yahoo"
+    },
+    "yahoogroups.com": {
+      "policy-alias": "yahoo"
+    },
+    "yandex.ru": {
+      "mode": "testing",
+      "mxs": [
+        ".yandex.ru"
+      ]
+    },
+    "ymail.com": {
+      "policy-alias": "yahoo"
+    },
+    "0xheap.org": {
+      "mode": "testing",
+      "mxs": [
+        "mail.0xheap.org"
+      ]
+    },
+    "alainwolf.ch": {
+      "mode": "testing",
+      "mxs": [
+        "pace.urown.net",
+        "norris.urown.net"
+      ]
+    },
+    "alainwolf.net": {
+      "mode": "testing",
+      "mxs": [
+        "norris.urown.net",
+        "pace.urown.net"
+      ]
+    },
+    "apbox.de": {
+      "mode": "testing",
+      "mxs": [
+        "srv.apbox.de"
+      ]
+    },
+    "avdagic.net": {
+      "mode": "testing",
+      "mxs": [
+        "avdagic.net"
+      ]
+    },
+    "bfg-10k.ru": {
+      "mode": "testing",
+      "mxs": [
+        "orion.bfg-10k.ru"
+      ]
+    },
+    "bitpath.de": {
+      "mode": "testing",
+      "mxs": [
+        "bitpath.de"
+      ]
+    },
+    "cfenns.de": {
+      "mode": "testing",
+      "mxs": [
+        "mail.cfenns.de"
+      ]
+    },
+    "chas.se": {
+      "mode": "testing",
+      "mxs": [
+        "mail.chas.se"
+      ]
+    },
+    "chatras.me": {
+      "mode": "testing",
+      "mxs": [
+        "smtp.chatras.me"
+      ]
+    },
+    "compucation.de": {
+      "mode": "testing",
+      "mxs": [
+        "mail.compucation.de"
+      ]
+    },
+    "crasline.de": {
+      "mode": "testing",
+      "mxs": [
+        "ina.pt-server.de"
+      ]
+    },
+    "dahoam.de": {
+      "mode": "testing",
+      "mxs": [
+        "cloud.eltrich.name",
+        "axon.gand.de"
+      ]
+    },
+    "davidkevork.me": {
+      "mode": "testing",
+      "mxs": [
+        "mx.zoho.com",
+        "mx2.zoho.com"
+      ]
+    },
+    "dayman.net": {
+      "mode": "testing",
+      "mxs": [
+        "dayman.net"
+      ]
+    },
+    "deepztream.com": {
+      "mode": "testing",
+      "mxs": [
+        "deepztream.com",
+        "mail.deepztream.com"
+      ]
+    },
+    "delfic.org": {
+      "mode": "testing",
+      "mxs": [
+        ".delfic.org"
+      ]
+    },
+    "dietrich.cx": {
+      "mode": "testing",
+      "mxs": [
+        "ybti.net"
+      ]
+    },
+    "eltrich.name": {
+      "mode": "testing",
+      "mxs": [
+        "cloud.eltrich.name",
+        "axon.gand.de"
+      ]
+    },
+    "eruditium.org": {
+      "mode": "testing",
+      "mxs": [
+        "mail.eruditium.org"
+      ]
+    },
+    "expertisale.com": {
+      "mode": "testing",
+      "mxs": [
+        "smtpmx2.expertisale.com",
+        "smtpmx3.expertisale.com"
+      ]
+    },
+    "fabje.nl": {
+      "mode": "testing",
+      "mxs": [
+        "mail.fabje.nl",
+        "in.hes.trendmicro.eu"
+      ]
+    },
+    "familieblume.nl": {
+      "mode": "testing",
+      "mxs": [
+        "in.hes.trendmicro.eu",
+        "mail.fabje.nl"
+      ]
+    },
+    "fau.org": {
+      "mode": "testing",
+      "mxs": [
+        "mail.fau.org"
+      ]
+    },
+    "fayeline.nl": {
+      "mode": "testing",
+      "mxs": [
+        "mail.fabje.nl"
+      ]
+    },
+    "federation-interstellar.org": {
+      "mode": "testing",
+      "mxs": [
+        "pace.urown.net",
+        "norris.urown.net"
+      ]
+    },
+    "fivl.it": {
+      "mode": "testing",
+      "mxs": [
+        ".fivl.it"
+      ]
+    },
+    "flawy.de": {
+      "mode": "testing",
+      "mxs": [
+        "lx1.flawy.de"
+      ]
+    },
+    "friendlyfire.ca": {
+      "mode": "testing",
+      "mxs": [
+        "mail.friendlyfire.ca"
+      ]
+    },
+    "gaertner-im-internet.de": {
+      "mode": "testing",
+      "mxs": [
+        "mailtomailserver08.de"
+      ]
+    },
+    "grepular.com": {
+      "mode": "testing",
+      "mxs": [
+        "mail.grepular.com",
+        "mx1.grepular.com"
+      ]
+    },
+    "gwalarn.eu": {
+      "mode": "testing",
+      "mxs": [
+        "gwalarn.eu",
+        "saintlu.gwalarn.eu"
+      ]
+    },
+    "hypermeganet.uk": {
+      "mode": "testing",
+      "mxs": [
+        "mail.hypermeganet.uk",
+        "mail2.hypermeganet.uk"
+      ]
+    },
+    "iddya.com": {
+      "mode": "testing",
+      "mxs": [
+        ".iddya.com"
+      ]
+    },
+    "itzer.de": {
+      "mode": "testing",
+      "mxs": [
+        "mail.itzer.de"
+      ]
+    },
+    "joelmediatv.de": {
+      "mode": "testing",
+      "mxs": [
+        "mail.codethink.de"
+      ]
+    },
+    "kjkobes.com": {
+      "mode": "testing",
+      "mxs": [
+        "in1-smtp.messagingengine.com",
+        "in2-smtp.messagingengine.com"
+      ]
+    },
+    "knthost.com": {
+      "mode": "testing",
+      "mxs": [
+        "mx.knthost.com",
+        "secure-mx.knthost.com",
+        "inbound01.knthost.com",
+        "secure-inbound01.knthost.com",
+        "inbound02.knthost.com",
+        "secure-inbound02.knthost.com"
+      ]
+    },
+    "krapace.fr": {
+      "mode": "testing",
+      "mxs": [
+        "mail.krapace.fr"
+      ]
+    },
+    "latinist.net": {
+      "mode": "testing",
+      "mxs": [
+        "latinist.net",
+        "mail.latinist.net"
+      ]
+    },
+    "linecorp.com": {
+      "mode": "testing",
+      "mxs": [
+        "mx1.navercorp.com",
+        "mx2.navercorp.com"
+      ]
+    },
+    "linuxfirewall.no-ip.org": {
+      "mode": "testing",
+      "mxs": [
+        "linuxfirewall.no-ip.org"
+      ]
+    },
+    "livoris.net": {
+      "mode": "testing",
+      "mxs": [
+        "livoris.net"
+      ]
+    },
+    "locker.email": {
+      "mode": "testing",
+      "mxs": [
+        "locker.email"
+      ]
+    },
+    "luup.info": {
+      "mode": "testing",
+      "mxs": [
+        "adrastea.luup.info"
+      ]
+    },
+    "macaw.me": {
+      "mode": "testing",
+      "mxs": [
+        "mail.macaw.me"
+      ]
+    },
+    "maddes.net": {
+      "mode": "testing",
+      "mxs": [
+        "mail.maddes.net"
+      ]
+    },
+    "miggy.org": {
+      "mode": "testing",
+      "mxs": [
+        "mail.fysh.org"
+      ]
+    },
+    "misguide.de": {
+      "mode": "testing",
+      "mxs": [
+        "h18.ogga.de"
+      ]
+    },
+    "modum.by": {
+      "mode": "testing",
+      "mxs": [
+        "mail.office.modum.by"
+      ]
+    },
+    "mpcompany.ru": {
+      "mode": "testing",
+      "mxs": [
+        "mx.mpcompany.ru",
+        ".mpcompany.ru"
+      ]
+    },
+    "mycloudmail.ooo": {
+      "mode": "testing",
+      "mxs": [
+        "mail.mycloudmail.ooo"
+      ]
+    },
+    "myriapolis.net": {
+      "mode": "testing",
+      "mxs": [
+        ".myriapolis.net"
+      ]
+    },
+    "naver.com": {
+      "mode": "testing",
+      "mxs": [
+        ".naver.com"
+      ]
+    },
+    "navercorp.com": {
+      "mode": "testing",
+      "mxs": [
+        ".navercorp.com"
+      ]
+    },
+    "neffets.de": {
+      "mode": "testing",
+      "mxs": [
+        "mail.neffets.de"
+      ]
+    },
+    "node-nine.com": {
+      "mode": "testing",
+      "mxs": [
+        "mx2.node-nine.com"
+      ]
+    },
+    "nottori.com": {
+      "mode": "testing",
+      "mxs": [
+        "mail.nottori.com"
+      ]
+    },
+    "pharmbiotest.com.ua": {
+      "mode": "testing",
+      "mxs": [
+        "pharmbiotest.com.ua"
+      ]
+    },
+    "pt-server.de": {
+      "mode": "testing",
+      "mxs": [
+        "ina.pt-server.de"
+      ]
+    },
+    "rbbaader.de": {
+      "mode": "testing",
+      "mxs": [
+        "ina.pt-server.de"
+      ]
+    },
+    "rbr.info": {
+      "mode": "testing",
+      "mxs": [
+        "mail.eruditium.org"
+      ]
+    },
+    "reisebuero-baader.de": {
+      "mode": "testing",
+      "mxs": [
+        "ina.pt-server.de"
+      ]
+    },
+    "saccani.net": {
+      "mode": "testing",
+      "mxs": [
+        ".fivl.it"
+      ]
+    },
+    "sheogorath.shivering-isles.com": {
+      "mode": "testing",
+      "mxs": [
+        "srv02.shivering-isles.com"
+      ]
+    },
+    "shivering-isles.com": {
+      "mode": "testing",
+      "mxs": [
+        "srv02.shivering-isles.com"
+      ]
+    },
+    "spodhuis.org": {
+      "mode": "testing",
+      "mxs": [
+        "mx.spodhuis.org"
+      ]
+    },
+    "teichsurfer.de": {
+      "mode": "testing",
+      "mxs": [
+        "one.teichsurfer.de"
+      ]
+    },
+    "thelinuxtree.net": {
+      "mode": "testing",
+      "mxs": [
+        ".thelinuxtree.net"
+      ]
+    },
+    "tspu.edu.ru": {
+      "mode": "testing",
+      "mxs": [
+        "mail.tspu.edu.ru"
+      ]
+    },
+    "tspu.ru": {
+      "mode": "testing",
+      "mxs": [
+        "mail.tspu.edu.ru"
+      ]
+    },
+    "4zal.net": {
+      "mode": "testing",
+      "mxs": [
+        "in1-smtp.messagingengine.com",
+        "in2-smtp.messagingengine.com"
+      ]
+    },
+    "anongoth.pl": {
+      "mode": "testing",
+      "mxs": [
+        "mail.anongoth.pl"
+      ]
+    },
+    "arkadiyt.com": {
+      "mode": "testing",
+      "mxs": [
+        "mail.protonmail.ch"
+      ]
+    },
+    "bingbong.epac.to": {
+      "mode": "testing",
+      "mxs": [
+        "bingbong.epac.to"
+      ]
+    },
+    "bjrn.io": {
+      "mode": "testing",
+      "mxs": [
+        "mail.bjrn.io"
+      ]
+    },
+    "boerner.click": {
+      "mode": "testing",
+      "mxs": [
+        ".boerner.click",
+        "hfyqtgmxim0iim3l.myfritz.net"
+      ]
+    },
+    "bolshaw.me.uk": {
+      "mode": "testing",
+      "mxs": [
+        "vm1.bolshaw.me.uk",
+        "vm2.bolshaw.me.uk"
+      ]
+    },
+    "c3w.at": {
+      "mode": "testing",
+      "mxs": [
+        "dergeraet.c3w.at"
+      ]
+    },
+    "cert.br": {
+      "mode": "testing",
+      "mxs": [
+        "woq.cert.br"
+      ]
+    },
+    "chamberlain.net.au": {
+      "mode": "testing",
+      "mxs": [
+        "mail.chamberlain.net.au",
+        "mail2.chamberlain.net.au",
+        "mail3.chamberlain.net.au"
+      ]
+    },
+    "clearbus.fr": {
+      "mode": "testing",
+      "mxs": [
+        "zimbra.clearbus.fr"
+      ]
+    },
+    "conchaudron.net": {
+      "mode": "testing",
+      "mxs": [
+        "mail.conchaudron.net",
+        ".conchaudron.net"
+      ]
+    },
+    "corecha.in": {
+      "mode": "testing",
+      "mxs": [
+        "mx.corecha.in"
+      ]
+    },
+    "cosysco.com": {
+      "mode": "testing",
+      "mxs": [
+        "mail.mobydog.net"
+      ]
+    },
+    "crustytoothpaste.net": {
+      "mode": "testing",
+      "mxs": [
+        ".crustytoothpaste.net"
+      ]
+    },
+    "decimatechnologies.eu": {
+      "mode": "testing",
+      "mxs": [
+        "in1-smtp.messagingengine.com",
+        "in2-smtp.messagingengine.com"
+      ]
+    },
+    "desgrange.net": {
+      "mode": "testing",
+      "mxs": [
+        ".desgrange.net"
+      ]
+    },
+    "desu.ne.jp": {
+      "mode": "testing",
+      "mxs": [
+        "kanna.desu.ne.jp",
+        "mx.desu.ne.jp"
+      ]
+    },
+    "dismail.de": {
+      "mode": "testing",
+      "mxs": [
+        "mx1.dismail.de"
+      ]
+    },
+    "druwe.net": {
+      "mode": "testing",
+      "mxs": [
+        "delores.druwe.net"
+      ]
+    },
+    "ergobyte.gr": {
+      "mode": "testing",
+      "mxs": [
+        ".ergobyte.gr"
+      ]
+    },
+    "f00f.org": {
+      "mode": "testing",
+      "mxs": [
+        ".stupidest.org"
+      ]
+    },
+    "familieverberne.nl": {
+      "mode": "testing",
+      "mxs": [
+        "smtp.verberne.nu"
+      ]
+    },
+    "fbreest.de": {
+      "mode": "testing",
+      "mxs": [
+        "mail.fbreest.de"
+      ]
+    },
+    "fireserve.com": {
+      "mode": "testing",
+      "mxs": [
+        "mail.fireserve.net",
+        "mx1.fireserve.net"
+      ]
+    },
+    "fireserve.net": {
+      "mode": "testing",
+      "mxs": [
+        "mail.fireserve.net",
+        "mx1.fireserve.net"
+      ]
+    },
+    "flarn.com": {
+      "mode": "testing",
+      "mxs": [
+        "mail.flarn.com"
+      ]
+    },
+    "fran.cr": {
+      "mode": "testing",
+      "mxs": [
+        ".fran.cr"
+      ]
+    },
+    "getappetite.tv": {
+      "mode": "testing",
+      "mxs": [
+        "mail.getappetite.tv"
+      ]
+    },
+    "ggp2.com": {
+      "mode": "testing",
+      "mxs": [
+        "c.fsckd.com",
+        "d.fsckd.com",
+        "e.fsckd.com"
+      ]
+    },
+    "gkd-el.de": {
+      "mode": "testing",
+      "mxs": [
+        "mailgw.gkd-el.de",
+        "filter.gkd-el.de"
+      ]
+    },
+    "guyromm.com": {
+      "mode": "testing",
+      "mxs": [
+        "mx.guyromm.com"
+      ]
+    },
+    "harrysmallbones.co.uk": {
+      "mode": "testing",
+      "mxs": [
+        "mail.harrysmallbones.co.uk",
+        "harrysmallbones.co.uk"
+      ]
+    },
+    "hesketh.net.au": {
+      "mode": "testing",
+      "mxs": [
+        "mail.hesketh.net.au"
+      ]
+    },
+    "incenp.org": {
+      "mode": "testing",
+      "mxs": [
+        "mail.incenp.org"
+      ]
+    },
+    "iq.pl": {
+      "mode": "testing",
+      "mxs": [
+        "mail.iq.pl"
+      ]
+    },
+    "jcea.es": {
+      "mode": "testing",
+      "mxs": [
+        "smtp.jcea.es"
+      ]
+    },
+    "jtg.business": {
+      "mode": "testing",
+      "mxs": [
+        "box.jtg.business"
+      ]
+    },
+    "jvb.ca": {
+      "mode": "testing",
+      "mxs": [
+        ".jvb.ca"
+      ]
+    },
+    "klausen.dk": {
+      "mode": "testing",
+      "mxs": [
+        "mail.klausen.dk"
+      ]
+    },
+    "klingele.me": {
+      "mode": "testing",
+      "mxs": [
+        "mail.leonklingele.de",
+        "alt1.mail.leonklingele.de",
+        "alt2.mail.leonklingele.de"
+      ]
+    },
+    "ko-sys.com": {
+      "mode": "testing",
+      "mxs": [
+        "smtp.ko-sys.com"
+      ]
+    },
+    "kubica.ch": {
+      "mode": "testing",
+      "mxs": [
+        ".kubica.ch"
+      ]
+    },
+    "levinus.de": {
+      "mode": "testing",
+      "mxs": [
+        "mail.levinus.de"
+      ]
+    },
+    "lifechurch.at": {
+      "mode": "testing",
+      "mxs": [
+        "mail.lifechurch.at"
+      ]
+    },
+    "maclemon.at": {
+      "mode": "testing",
+      "mxs": [
+        "dungeon.maclemon.at",
+        "prometheus.maclemon.at"
+      ]
+    },
+    "menthiere.fr": {
+      "mode": "testing",
+      "mxs": [
+        ".mail.gandi.net"
+      ]
+    },
+    "michaelpjohnson.com": {
+      "mode": "testing",
+      "mxs": [
+        "mail.michaelpjohnson.com",
+        "michaelpjohnson.com"
+      ]
+    },
+    "mnium.de": {
+      "mode": "testing",
+      "mxs": [
+        "mail.mnium.de"
+      ]
+    },
+    "monopod.net": {
+      "mode": "testing",
+      "mxs": [
+        ".electricembers.net"
+      ]
+    },
+    "nic.br": {
+      "mode": "testing",
+      "mxs": [
+        "mail.nic.br",
+        "enqueuer.nic.br"
+      ]
+    },
+    "ninetailed.ninja": {
+      "mode": "testing",
+      "mxs": [
+        ".ninetailed.ninja"
+      ]
+    },
+    "ninov.de": {
+      "mode": "testing",
+      "mxs": [
+        "ofen.nv.gw"
+      ]
+    },
+    "nothing.net.nz": {
+      "mode": "testing",
+      "mxs": [
+        "aspmx.l.google.com",
+        "alt1.aspmx.l.google.com",
+        "alt2.aspmx.l.google.com"
+      ]
+    },
+    "petersons.me": {
+      "mode": "testing",
+      "mxs": [
+        "mail.protonmail.ch"
+      ]
+    },
+    "pf.id.au": {
+      "mode": "testing",
+      "mxs": [
+        ".pf.id.au",
+        ".ironicfate.com.au"
+      ]
+    },
+    "ppt.com": {
+      "mode": "testing",
+      "mxs": [
+        ".ppt.com"
+      ]
+    },
+    "privacyweek.at": {
+      "mode": "testing",
+      "mxs": [
+        "dergeraet.c3w.at"
+      ]
+    },
+    "raitisoja.com": {
+      "mode": "testing",
+      "mxs": [
+        "box.prvcy.email"
+      ]
+    },
+    "randolf.at": {
+      "mode": "testing",
+      "mxs": [
+        "mail.randolf.at"
+      ]
+    },
+    "registro.br": {
+      "mode": "testing",
+      "mxs": [
+        "clone.registro.br",
+        "clonev4.registro.br",
+        "fe.registro.br"
+      ]
+    },
+    "s-hertogenbosch.nl": {
+      "mode": "testing",
+      "mxs": [
+        "mx1.s-hertogenbosch.nl",
+        "mx2.s-hertogenbosch.nl"
+      ]
+    },
+    "sauerburger.io": {
+      "mode": "testing",
+      "mxs": [
+        "mail.sit-servers.net"
+      ]
+    },
+    "sbs.co.nz": {
+      "mode": "testing",
+      "mxs": [
+        "mail.sbs.co.nz"
+      ]
+    },
+    "schlarb.eu": {
+      "mode": "testing",
+      "mxs": [
+        ".ninetailed.ninja"
+      ]
+    },
+    "sdeziel.info": {
+      "mode": "testing",
+      "mxs": [
+        "smtp.sdeziel.info"
+      ]
+    },
+    "sertelon.fr": {
+      "mode": "testing",
+      "mxs": [
+        "smtp.sertelon.fr"
+      ]
+    },
+    "sixpak.org": {
+      "mode": "testing",
+      "mxs": [
+        "sixpak.sixpak.org"
+      ]
+    },
+    "sufix.cz": {
+      "mode": "testing",
+      "mxs": [
+        "mail.sufix.cz",
+        "sufix.cz"
+      ]
+    },
+    "sunsetdynamics.com": {
+      "mode": "testing",
+      "mxs": [
+        "mail.fireserve.net",
+        "mx1.fireserve.net"
+      ]
+    },
+    "sven.de": {
+      "mode": "testing",
+      "mxs": [
+        "mail.sven.de"
+      ]
+    },
+    "tala.dk": {
+      "mode": "testing",
+      "mxs": [
+        "mail.tala.dk",
+        "smtp.tala.dk",
+        "tala.dk"
+      ]
+    },
+    "tepas.de": {
+      "mode": "testing",
+      "mxs": [
+        "mail.tepas.de"
+      ]
+    },
+    "tgoss.de": {
+      "mode": "testing",
+      "mxs": [
+        "tgoss.de"
+      ]
+    },
+    "thenetw.org": {
+      "mode": "testing",
+      "mxs": [
+        "thenetw-org.mail.protection.outlook.com"
+      ]
+    },
+    "thewiesners.org": {
+      "mode": "testing",
+      "mxs": [
+        "box.thewiesners.org",
+        "thewiesners.org"
+      ]
+    },
+    "tifaware.com": {
+      "mode": "testing",
+      "mxs": [
+        "sal.tifaware.com",
+        "mail.tifaware.com"
+      ]
+    },
+    "tilde.team": {
+      "mode": "testing",
+      "mxs": [
+        ".tilde.team"
+      ]
+    },
+    "tynan.com": {
+      "mode": "testing",
+      "mxs": [
+        "cloud.tynan.com"
+      ]
+    },
+    "valorizmusic.com": {
+      "mode": "testing",
+      "mxs": [
+        ".ninetailed.ninja"
+      ]
+    },
+    "volitans-software.com": {
+      "mode": "testing",
+      "mxs": [
+        "mail.volitans-software.com"
+      ]
+    },
+    "vosky.fr": {
+      "mode": "testing",
+      "mxs": [
+        "aga.vosky.fr",
+        "scw.vosky.fr"
+      ]
+    },
+    "wakesecure.com": {
+      "mode": "testing",
+      "mxs": [
+        "wakesecure.com",
+        "marcabel.com"
+      ]
+    },
+    "webgma.co.il": {
+      "mode": "testing",
+      "mxs": [
+        "mx.webgma.co.il"
+      ]
+    },
+    "xel.nl": {
+      "mode": "testing",
+      "mxs": [
+        "mx1.xel.nl",
+        "mx2.xel.nl",
+        "mx3.xel.nl"
+      ]
+    },
+    "yoursafe.se": {
+      "mode": "testing",
+      "mxs": [
+        "mail.yoursafe.se"
+      ]
+    },
+    "zl1ab.nz": {
+      "mode": "testing",
+      "mxs": [
+        "zl1ab.nz"
+      ]
+    },
+    "babioch.de": {
+      "mode": "testing",
+      "mxs": [
+        "mail.babioch.de"
+      ]
+    },
+    "bpce.fr": {
+      "mode": "testing",
+      "mxs": [
+        "mail-in.bpce-it.fr"
+      ]
+    },
+    "curttech.com": {
+      "mode": "testing",
+      "mxs": [
+        "mail.curttech.net"
+      ]
+    },
+    "dhautefeuille.eu": {
+      "mode": "testing",
+      "mxs": [
+        "arch-server.dhautefeuille.eu"
+      ]
+    },
+    "duesterhus.eu": {
+      "mode": "testing",
+      "mxs": [
+        ".xqk7.com"
+      ]
+    },
+    "durel.org": {
+      "mode": "testing",
+      "mxs": [
+        "arrakeen.geekwu.org",
+        "corrin.geekwu.org"
+      ]
+    },
+    "eckhofer.com": {
+      "mode": "testing",
+      "mxs": [
+        "mail.tribut.de"
+      ]
+    },
+    "edam-volendam.nl": {
+      "mode": "testing",
+      "mxs": [
+        "gen1.edam-volendam.nl"
+      ]
+    },
+    "fladnag.net": {
+      "mode": "testing",
+      "mxs": [
+        "mail.fladnag.net",
+        "gateway.mail.fladnag.net"
+      ]
+    },
+    "hany.sk": {
+      "mode": "testing",
+      "mxs": [
+        ".hany.sk"
+      ]
+    },
+    "hewgill.net": {
+      "mode": "testing",
+      "mxs": [
+        "stratus.hewgill.net"
+      ]
+    },
+    "it4sure.nl": {
+      "mode": "testing",
+      "mxs": [
+        "mx1.it4sure.cloud",
+        "mx2.it4sure.cloud",
+        "mail.it4sure.cloud"
+      ]
+    },
+    "jndata.dk": {
+      "mode": "testing",
+      "mxs": [
+        "mailin01.jndata.dk",
+        "mailin02.jndata.dk",
+        "mailin03.jndata.dk"
+      ]
+    },
+    "knop.eu": {
+      "mode": "testing",
+      "mxs": [
+        "srv01.knop.info"
+      ]
+    },
+    "lancashirebeekeepers.org.uk": {
+      "mode": "testing",
+      "mxs": [
+        "aspmx.l.google.com",
+        "alt1.aspmx.l.google.com",
+        "alt2.aspmx.l.google.com",
+        "aspmx2.googlemail.com",
+        "aspmx3.googlemail.com"
+      ]
+    },
+    "ledovskis.lv": {
+      "mode": "testing",
+      "mxs": [
+        "ariake.ledovskis.lv"
+      ]
+    },
+    "lmcm.io": {
+      "mode": "testing",
+      "mxs": [
+        "in1-smtp.messagingengine.com",
+        "in2-smtp.messagingengine.com"
+      ]
+    },
+    "mail.de": {
+      "mode": "testing",
+      "mxs": [
+        ".mail.de"
+      ]
+    },
+    "mattleidholm.com": {
+      "mode": "testing",
+      "mxs": [
+        "in1-smtp.messagingengine.com",
+        "in2-smtp.messagingengine.com"
+      ]
+    },
+    "mingjie.info": {
+      "mode": "testing",
+      "mxs": [
+        ".mingjie.info",
+        ".messagingengine.com"
+      ]
+    },
+    "netcompany.com": {
+      "mode": "testing",
+      "mxs": [
+        "netcompany-com.mail.protection.outlook.com"
+      ]
+    },
+    "netgalaxy.ca": {
+      "mode": "testing",
+      "mxs": [
+        "nyc.netgalaxy.ca"
+      ]
+    },
+    "ozark.be": {
+      "mode": "testing",
+      "mxs": [
+        "mail.hypnotized.org"
+      ]
+    },
+    "pa5am.nl": {
+      "mode": "testing",
+      "mxs": [
+        "pa5am.nl"
+      ]
+    },
+    "sanker.by": {
+      "mode": "testing",
+      "mxs": [
+        "mail.sanker.by"
+      ]
+    },
+    "santoshpandit.com": {
+      "mode": "testing",
+      "mxs": [
+        "node487.myfcloud.com",
+        "mx.santoshpandit.com",
+        "mail.santoshpandit.com"
+      ]
+    },
+    "saskpension.com": {
+      "mode": "testing",
+      "mxs": [
+        "saskpension-com.mail.protection.outlook.com"
+      ]
+    },
+    "seffner-schlesier.de": {
+      "mode": "testing",
+      "mxs": [
+        ".seffner-schlesier.de"
+      ]
+    },
+    "sovereign-order-of-saint-john.org": {
+      "mode": "testing",
+      "mxs": [
+        "mxext1.mailbox.org",
+        "mxext2.mailbox.org",
+        "mxext3.mailbox.org"
+      ]
+    },
+    "t-senger.de": {
+      "mode": "testing",
+      "mxs": [
+        ".t-senger.de"
+      ]
+    },
+    "taintedbit.com": {
+      "mode": "testing",
+      "mxs": [
+        "mail.taintedbit.com"
+      ]
+    },
+    "thisishugo.com": {
+      "mode": "testing",
+      "mxs": [
+        "in1-smtp.messagingengine.com",
+        "in2-smtp.messagingengine.com"
+      ]
+    },
+    "vixrapedia.org": {
+      "mode": "testing",
+      "mxs": [
+        "mail.vixrapedia.org"
+      ]
+    },
+    "vulnscan.org": {
+      "mode": "testing",
+      "mxs": [
+        "mail.vulnscan.org"
+      ]
+    },
+    "w4eg.de": {
+      "mode": "testing",
+      "mxs": [
+        "w4eg.de"
+      ]
+    },
+    "wiktel.com": {
+      "mode": "testing",
+      "mxs": [
+        "mail.wiktel.com",
+        "mx.wiktel.com"
+      ]
+    },
+    "xylon.de": {
+      "mode": "testing",
+      "mxs": [
+        "mail.xylon.de"
+      ]
+    },
+    "aegee.org": {
+      "mode": "testing",
+      "mxs": [
+        "mail.aegee.org"
+      ]
+    },
+    "anthonyvadala.me": {
+      "mode": "testing",
+      "mxs": [
+        "mail.protonmail.ch",
+        "mailsec.protonmail.ch"
+      ]
+    },
+    "artikel10.org": {
+      "mode": "testing",
+      "mxs": [
+        "ybti.net"
+      ]
+    },
+    "aztecface.email": {
+      "mode": "testing",
+      "mxs": [
+        "mail.protonmail.ch",
+        "mailsec.protonmail.ch"
+      ]
+    },
+    "backschues.com": {
+      "mode": "testing",
+      "mxs": [
+        "mx0.backschues.net"
+      ]
+    },
+    "backschues.de": {
+      "mode": "testing",
+      "mxs": [
+        "mx0.backschues.net",
+        "mx00.backschues.net",
+        "mx1.backschues.net",
+        "mx01.backschues.net"
+      ]
+    },
+    "backschues.net": {
+      "mode": "testing",
+      "mxs": [
+        "mx0.backschues.net"
+      ]
+    },
+    "bearsunderland.com": {
+      "mode": "testing",
+      "mxs": [
+        "aspmx.l.google.com",
+        "alt1.aspmx.l.google.com",
+        "alt2.aspmx.l.google.com",
+        "aspmx2.googlemail.com",
+        "aspmx3.googlemail.com"
+      ]
+    },
+    "benjamin.computer": {
+      "mode": "testing",
+      "mxs": [
+        "mail.section9.london",
+        "post.section9.london"
+      ]
+    },
+    "billaud.eu.org": {
+      "mode": "testing",
+      "mxs": [
+        "billaud.eu.org",
+        "www2.billaud.eu.org"
+      ]
+    },
+    "boenning.me": {
+      "mode": "testing",
+      "mxs": [
+        "mail.protonmail.ch",
+        "mailsec.protonmail.ch"
+      ]
+    },
+    "bolte.org": {
+      "mode": "testing",
+      "mxs": [
+        "mail.bolte.org"
+      ]
+    },
+    "bornwebserver.nl": {
+      "mode": "testing",
+      "mxs": [
+        "bornwebserver.nl",
+        "mail.bornwebserver.nl"
+      ]
+    },
+    "bugabinga.net": {
+      "mode": "testing",
+      "mxs": [
+        "box.bugabinga.net"
+      ]
+    },
+    "caletka.cz": {
+      "mode": "testing",
+      "mxs": [
+        ".oskarcz.net",
+        ".caletka.cz"
+      ]
+    },
+    "castlehoward.co.uk": {
+      "mode": "testing",
+      "mxs": [
+        "mail.castlehoward.co.uk"
+      ]
+    },
+    "cdom.de": {
+      "mode": "testing",
+      "mxs": [
+        "mailfilter2.cdom.de"
+      ]
+    },
+    "ck-energy.de": {
+      "mode": "testing",
+      "mxs": [
+        "alpha.mail.ck-energy.info",
+        "beta.mail.ck-energy.info"
+      ]
+    },
+    "colincogle.name": {
+      "mode": "testing",
+      "mxs": [
+        "ec2.rhymeswithmogul.com",
+        "azure.rhymeswithmogul.com"
+      ]
+    },
+    "connordav.is": {
+      "mode": "testing",
+      "mxs": [
+        "mx.zoho.com",
+        "mx2.zoho.com",
+        "mx3.zoho.com"
+      ]
+    },
+    "dancingsnails.com": {
+      "mode": "testing",
+      "mxs": [
+        "mail.dancingsnails.com"
+      ]
+    },
+    "ddimension.net": {
+      "mode": "testing",
+      "mxs": [
+        "gamenet.ddimension.net"
+      ]
+    },
+    "divegearexpress.com": {
+      "mode": "testing",
+      "mxs": [
+        "smtp.divegearexpress.com",
+        "in1-smtp.messagingengine.com",
+        "in2-smtp.messagingengine.com"
+      ]
+    },
+    "domblogger.net": {
+      "mode": "testing",
+      "mxs": [
+        "mail.domblogger.net"
+      ]
+    },
+    "donnerdoof.de": {
+      "mode": "testing",
+      "mxs": [
+        "mail.donnerdoof.de"
+      ]
+    },
+    "e9a.at": {
+      "mode": "testing",
+      "mxs": [
+        "mail.e9a.at"
+      ]
+    },
+    "email.ctrl.blog": {
+      "mode": "testing",
+      "mxs": [
+        "email.ctrl.blog"
+      ]
+    },
+    "french-interface.com": {
+      "mode": "testing",
+      "mxs": [
+        "french-interface.com"
+      ]
+    },
+    "fruweb.de": {
+      "mode": "testing",
+      "mxs": [
+        "hermes.fruweb.de",
+        ".mailbox.org"
+      ]
+    },
+    "gehrke.in": {
+      "mode": "testing",
+      "mxs": [
+        "mx0.backschues.net",
+        "mx1.backschues.net",
+        "mx00.backschues.net",
+        "mx01.backschues.net"
+      ]
+    },
+    "giebel.it": {
+      "mode": "testing",
+      "mxs": [
+        "mailfilter2.cdom.de"
+      ]
+    },
+    "goppold.net": {
+      "mode": "testing",
+      "mxs": [
+        "mail.goppold.net",
+        "mail2.goppold.net"
+      ]
+    },
+    "halla.lv": {
+      "mode": "testing",
+      "mxs": [
+        "mail.halla.lv"
+      ]
+    },
+    "hengroenet.de": {
+      "mode": "testing",
+      "mxs": [
+        "mail.hengroenet.de"
+      ]
+    },
+    "honigdachse.de": {
+      "mode": "testing",
+      "mxs": [
+        ".honigdachse.de",
+        "mail.honigdachse.de"
+      ]
+    },
+    "iatmgu.com": {
+      "mode": "testing",
+      "mxs": [
+        "mail.iatmgu.com"
+      ]
+    },
+    "inethost.eu": {
+      "mode": "testing",
+      "mxs": [
+        "mail.inethost.eu"
+      ]
+    },
+    "it-zahner.de": {
+      "mode": "testing",
+      "mxs": [
+        "mx.it-zahner.net"
+      ]
+    },
+    "jonaswitmer.ch": {
+      "mode": "testing",
+      "mxs": [
+        "jonaswitmer.ch"
+      ]
+    },
+    "js-webcoding.de": {
+      "mode": "testing",
+      "mxs": [
+        "mail.js-webcoding.de"
+      ]
+    },
+    "kc1hbk.com": {
+      "mode": "testing",
+      "mxs": [
+        "ec2.rhymeswithmogul.com",
+        "azure.rhymeswithmogul.com"
+      ]
+    },
+    "kimihia.org.nz": {
+      "mode": "testing",
+      "mxs": [
+        "in1-smtp.messagingengine.com",
+        "in2-smtp.messagingengine.com"
+      ]
+    },
+    "kmm.im": {
+      "mode": "testing",
+      "mxs": [
+        "mail.domob.eu"
+      ]
+    },
+    "koehn-consulting.com": {
+      "mode": "testing",
+      "mxs": [
+        ".koehn.com"
+      ]
+    },
+    "koehn.com": {
+      "mode": "testing",
+      "mxs": [
+        ".koehn.com",
+        "aspmx3.googlemail.com",
+        "aspmx4.googlemail.com",
+        "aspmx5.googlemail.com",
+        "aspmx.l.google.com",
+        "aspmx2.googlemail.com",
+        "alt1.aspmx.l.google.com",
+        "alt2.aspmx.l.google.com"
+      ]
+    },
+    "kryptonresearch.com": {
+      "mode": "testing",
+      "mxs": [
+        "mail.tutanota.de"
+      ]
+    },
+    "laxu.de": {
+      "mode": "testing",
+      "mxs": [
+        "mx.nanubo.de"
+      ]
+    },
+    "lemon-kiwi.co": {
+      "mode": "testing",
+      "mxs": [
+        "alt4.aspmx.l.google.com",
+        "alt3.aspmx.l.google.com",
+        "alt1.aspmx.l.google.com",
+        "aspmx.l.google.com",
+        "alt2.aspmx.l.google.com"
+      ]
+    },
+    "librelamp.com": {
+      "mode": "testing",
+      "mxs": [
+        "librelamp.com"
+      ]
+    },
+    "m9r1s.com": {
+      "mode": "testing",
+      "mxs": [
+        "mail.m9r1s.com",
+        "m9r1s.com"
+      ]
+    },
+    "mach-politik.ch": {
+      "mode": "testing",
+      "mxs": [
+        "mach-politik.ch"
+      ]
+    },
+    "mahlendur.de": {
+      "mode": "testing",
+      "mxs": [
+        "mail.mahlendur.de"
+      ]
+    },
+    "mail.aegee.org": {
+      "mode": "testing",
+      "mxs": [
+        "mail.aegee.org"
+      ]
+    },
+    "mail.com": {
+      "mode": "testing",
+      "mxs": [
+        "mx00.mail.com",
+        "mx01.mail.com"
+      ]
+    },
+    "megane.it": {
+      "mode": "testing",
+      "mxs": [
+        "mail.megane.it",
+        "mail2.megane.it",
+        "mail3.megane.it"
+      ]
+    },
+    "meproduction.org": {
+      "mode": "testing",
+      "mxs": [
+        "meproduction.org",
+        ".meproduction.org",
+        "mail.meproduction.org"
+      ]
+    },
+    "mercedcapital.com": {
+      "mode": "testing",
+      "mxs": [
+        "smtp1-msp.securence.com",
+        "smtp1-mke.securence.com"
+      ]
+    },
+    "mewp.pl": {
+      "mode": "testing",
+      "mxs": [
+        "mail.mewp.pl"
+      ]
+    },
+    "naundorf.it": {
+      "mode": "testing",
+      "mxs": [
+        "mail.bummelwelt.com"
+      ]
+    },
+    "netera.com": {
+      "mode": "testing",
+      "mxs": [
+        "aspmx.l.google.com",
+        "alt1.aspmx.l.google.com",
+        "alt2.aspmx.l.google.com",
+        "alt3.aspmx.l.google.com",
+        "alt4.aspmx.l.google.com"
+      ]
+    },
+    "onex.de": {
+      "mode": "testing",
+      "mxs": [
+        "efa1.onexdienste.de",
+        "efa2.onexdienste.de"
+      ]
+    },
+    "pienpa.nl": {
+      "mode": "testing",
+      "mxs": [
+        "mail.pienpa.nl"
+      ]
+    },
+    "piratenpartei.at": {
+      "mode": "testing",
+      "mxs": [
+        "piratenpartei.at",
+        "pikachu.piratenpartei.at"
+      ]
+    },
+    "piratenpartei.de": {
+      "mode": "testing",
+      "mxs": [
+        "mail.piratenpartei.de",
+        "piratenpartei.de"
+      ]
+    },
+    "projectografico.com": {
+      "mode": "testing",
+      "mxs": [
+        "mail.projectografico.com"
+      ]
+    },
+    "protonmail.com": {
+      "mode": "testing",
+      "mxs": [
+        "protonmail.com",
+        ".protonlabs.org",
+        ".protonmail.com",
+        ".protonvpn.ch",
+        ".protonvpn.com",
+        ".protonmail.ch",
+        "protonmail.ch",
+        ".pm.me"
+      ]
+    },
+    "robwillis.org": {
+      "mode": "testing",
+      "mxs": [
+        "vade-in1.mail.dreamhost.com",
+        "vade-in2.mail.dreamhost.com"
+      ]
+    },
+    "rupostel.com": {
+      "mode": "testing",
+      "mxs": [
+        "mx.aububu.com"
+      ]
+    },
+    "s2net.ch": {
+      "mode": "testing",
+      "mxs": [
+        "smtp.s2net.ch"
+      ]
+    },
+    "salford.gov.uk": {
+      "mode": "testing",
+      "mxs": [
+        "mailmx.salford.gov.uk",
+        "mailout.ictservices.co.uk"
+      ]
+    },
+    "sandbornvoglfarms.com": {
+      "mode": "testing",
+      "mxs": [
+        "www.sandbornvoglfarms.com"
+      ]
+    },
+    "saulchristie.com": {
+      "mode": "testing",
+      "mxs": [
+        "aspmx.l.google.com",
+        "alt1.aspmx.l.google.com",
+        "alt2.aspmx.l.google.com",
+        "alt3.aspmx.l.google.com",
+        "alt4.aspmx.l.google.com"
+      ]
+    },
+    "schleifenbaum.email": {
+      "mode": "testing",
+      "mxs": [
+        "mail.js-webcoding.de"
+      ]
+    },
+    "schleifenbaum.org": {
+      "mode": "testing",
+      "mxs": [
+        "mail.js-webcoding.de"
+      ]
+    },
+    "scotthsmith.com": {
+      "mode": "testing",
+      "mxs": [
+        "in1-smtp.messagingengine.com",
+        "in2-smtp.messagingengine.com"
+      ]
+    },
+    "secure.mailbox.org": {
+      "mode": "testing",
+      "mxs": [
+        "mxtls1.mailbox.org",
+        "mxtls2.mailbox.org"
+      ]
+    },
+    "seite3.net": {
+      "mode": "testing",
+      "mxs": [
+        "post.seite3.net"
+      ]
+    },
+    "semox.de": {
+      "mode": "testing",
+      "mxs": [
+        "www.semox.de"
+      ]
+    },
+    "setemares.org": {
+      "mode": "testing",
+      "mxs": [
+        "mail.setemares.org"
+      ]
+    },
+    "skynet-devices.com": {
+      "mode": "testing",
+      "mxs": [
+        "mail.tutanota.de"
+      ]
+    },
+    "snowpaws.de": {
+      "mode": "testing",
+      "mxs": [
+        "mail.snowpaws.de"
+      ]
+    },
+    "sodium.gr": {
+      "mode": "testing",
+      "mxs": [
+        "mail.sodium.gr"
+      ]
+    },
+    "srs-sys.de": {
+      "mode": "testing",
+      "mxs": [
+        "mx01a.srs-sys.de",
+        "mx01b.srs-sys.de",
+        "mx02a.srs-sys.de",
+        "mx02b.srs-sys.de"
+      ]
+    },
+    "svengo.de": {
+      "mode": "testing",
+      "mxs": [
+        "mail.svengo.net"
+      ]
+    },
+    "systemausfall.org": {
+      "mode": "testing",
+      "mxs": [
+        "mx1.systemausfall.org",
+        "mx2.systemausfall.org"
+      ]
+    },
+    "tbz-pariv.de": {
+      "mode": "testing",
+      "mxs": [
+        "mail.tbz-pariv.de",
+        "mail2.tbz-pariv.de"
+      ]
+    },
+    "technikumnukleoniczne.pl": {
+      "mode": "testing",
+      "mxs": [
+        "TechnikumNukleoniczne-pl.mail.protection.outlook.com"
+      ]
+    },
+    "the.sexy": {
+      "mode": "testing",
+      "mxs": [
+        "mail.the.sexy"
+      ]
+    },
+    "thinking-bit.com": {
+      "mode": "testing",
+      "mxs": [
+        "mail.thinking-bit.com"
+      ]
+    },
+    "thinktank.co.nz": {
+      "mode": "testing",
+      "mxs": [
+        "thinktank.co.nz",
+        "mail.thinktank.co.nz",
+        "mail2.thinktank.co.nz",
+        "southern.thinktank.co.nz"
+      ]
+    },
+    "tresdouteux.com": {
+      "mode": "testing",
+      "mxs": [
+        "mail.protonmail.ch"
+      ]
+    },
+    "treussart.com": {
+      "mode": "testing",
+      "mxs": [
+        ".treussart.com"
+      ]
+    },
+    "tutanota.com": {
+      "mode": "testing",
+      "mxs": [
+        "mail.tutanota.de"
+      ]
+    },
+    "vm-0.com": {
+      "mode": "testing",
+      "mxs": [
+        "mx.vm-0.com"
+      ]
+    },
+    "waldkindergarten-ausstattung.de": {
+      "mode": "testing",
+      "mxs": [
+        "mail.bummelwelt.com"
+      ]
+    },
+    "ybti.net": {
+      "mode": "testing",
+      "mxs": [
+        "ybti.net"
+      ]
+    },
+    "zip-support.de": {
+      "mode": "testing",
+      "mxs": [
+        "mail.zip-support.de"
+      ]
+    }
+  }
+}
\ No newline at end of file
diff --git a/test/confs/2750 b/test/confs/2750
new file mode 100644 (file)
index 0000000..08e66bf
--- /dev/null
@@ -0,0 +1,5 @@
+# Exim test configuration 2750
+
+exim_path = EXIM_PATH
+
+# End
diff --git a/test/scripts/2750-json/2750 b/test/scripts/2750-json/2750
new file mode 100644 (file)
index 0000000..f01414b
--- /dev/null
@@ -0,0 +1,22 @@
+# lookup json
+#
+exim -be
+policy-aliases:google:mode
+${lookup {policy-aliases:google:mode} json {DIR/aux-fixed/policy.json}}
+
+policies:hotmail.com
+${lookup {policies:hotmail.com} json {DIR/aux-fixed/policy.json}}
+
+policy-aliases:outlook
+${lookup {policy-aliases:outlook} json {DIR/aux-fixed/policy.json}}
+
+policy-aliases:outlook:mxs
+${lookup {policy-aliases:outlook:mxs} json {DIR/aux-fixed/policy.json}}
+
+policy-aliases:outlook:mxs:1
+${lookup {policy-aliases : outlook : mxs : 1} json {DIR/aux-fixed/policy.json}}
+
+aggregate output vs. json extract
+${extract json {mxs} \
+       {${lookup {policy-aliases:outlook} json {DIR/aux-fixed/policy.json}}}}
+****
diff --git a/test/scripts/2750-json/REQUIRES b/test/scripts/2750-json/REQUIRES
new file mode 100644 (file)
index 0000000..34b0003
--- /dev/null
@@ -0,0 +1 @@
+lookup json
diff --git a/test/stdout/2750 b/test/stdout/2750
new file mode 100644 (file)
index 0000000..d70041a
--- /dev/null
@@ -0,0 +1,18 @@
+> policy-aliases:google:mode
+> testing
+> 
+> policies:hotmail.com
+> {"policy-alias": "outlook"}
+> 
+> policy-aliases:outlook
+> {"mode": "testing", "mxs": [".outlook.com", "outlook.com"]}
+> 
+> policy-aliases:outlook:mxs
+> [".outlook.com", "outlook.com"]
+> 
+> policy-aliases:outlook:mxs:1
+> outlook.com
+> 
+> aggregate output vs. json extract
+> [".outlook.com", "outlook.com"]
+>