diff --git a/mutalyzer/Scheduler.py b/mutalyzer/Scheduler.py
index f82671a709cc553172c4e2082220978049b47c0b..f3ad60e6d86331722752e957402d5b17f45ab6d5 100644
--- a/mutalyzer/Scheduler.py
+++ b/mutalyzer/Scheduler.py
@@ -97,9 +97,9 @@ class Scheduler() :
         if settings.TESTING:
             return
 
-        # Mail is set to 'job@webservice' if the batch job was submitted using
-        # the webservice.
-        if mailTo == 'job@webservice':
+        # Mail is set to '<IP ADDRESS>@webservice' if the batch job was
+        # submitted using the webservice without specifying an email address.
+        if mailTo.endswith('@webservice'):
             return
 
         #TODO: Handle Connection errors in a try, except clause
diff --git a/mutalyzer/entrypoints/admin.py b/mutalyzer/entrypoints/admin.py
index d41df6143df7ff7b3f4e8a1598494393abf7132b..b0d26f357b5e8bb8a5266628420fc6efce6407d3 100644
--- a/mutalyzer/entrypoints/admin.py
+++ b/mutalyzer/entrypoints/admin.py
@@ -186,8 +186,8 @@ def list_batch_jobs():
         'email_len': max(len(j.email) for j, _ in batch_jobs_with_counts)
     }
 
-    template = ('{id:{id_len}}  {type:<{type_len}}  {added:%Y-%m-%d %H:%M:%S}'
-                '  {count:<{count_len}}  {email:{email_len}}')
+    template = ('{id:>{id_len}}  {type:{type_len}}  {added:%Y-%m-%d %H:%M:%S}'
+                '  {count:>{count_len}}  {email:{email_len}}')
 
     for batch_job, count in batch_jobs_with_counts:
         print template.format(
diff --git a/mutalyzer/services/rpc.py b/mutalyzer/services/rpc.py
index 8281da387b4049ffbbdcc7d1410d07cf00d4db66..508cd90530491ea8c0448ee2134fad35ab5c4b4f 100644
--- a/mutalyzer/services/rpc.py
+++ b/mutalyzer/services/rpc.py
@@ -12,7 +12,7 @@ Mutalyzer RPC services.
 from __future__ import unicode_literals
 
 import binning
-from spyne.decorator import srpc
+from spyne.decorator import rpc, srpc
 from spyne.service import ServiceBase
 from spyne.model.primitive import Integer, Boolean, DateTime, Unicode
 from spyne.model.complex import Array
@@ -71,8 +71,8 @@ class MutalyzerService(ServiceBase):
         super(MutalyzerService, self).__init__(environ)
     #__init__
 
-    @srpc(Mandatory.ByteArray, Unicode, Unicode, Unicode, _returns=Unicode)
-    def submitBatchJob(data, process='NameChecker', argument='', email=None):
+    @rpc(Mandatory.ByteArray, Unicode, Unicode, Unicode, _returns=Unicode)
+    def submitBatchJob(ctx, data, process='NameChecker', argument='', email=None):
         """
         Submit a batch job.
 
@@ -80,10 +80,10 @@ class MutalyzerService(ServiceBase):
         website <https://mutalyzer.nl/batch>.
 
         Batch jobs are processed using round-robin scheduling grouped by email
-        address. Per email address, jobs are processed sequentially in order
-        of submission. Jobs with no email address specified end up in a shared
-        group. This means your job is likely to be processed sooner if you
-        provide an email address.
+        address (or client IP address if no email address is specified). Per
+        email address, jobs are processed sequentially in order of submission.
+        This means you will not see any progress on this job until all your
+        earlier jobs have finished.
 
         On error an exception is raised:
           - detail: Human readable description of the error.
@@ -147,7 +147,17 @@ class MutalyzerService(ServiceBase):
         if job is None:
             raise Fault('EPARSE', 'Could not parse input file, please check your file format.')
 
-        result_id = scheduler.addJob(email or 'job@webservice', job, columns,
+        if not email:
+            # If no email address is specified, we create a fake one based on
+            # the caller's IP address. This makes sure the scheduler processes
+            # jobs grouped by user.
+            try:
+                address = unicode(ctx.transport.req_env['REMOTE_ADDR'])
+            except (AttributeError, KeyError):
+                address = 'localhost'
+            email = '%s@webservice' % address
+
+        result_id = scheduler.addJob(email, job, columns,
                                      batch_types[process], argument)
         return result_id
 
diff --git a/mutalyzer/website/templates/static/js/interface.js b/mutalyzer/website/templates/static/js/interface.js
index 7960c2b025c73cd99f444d3d3136df196a1f5e3a..d78c1f61ac1ff36492f3844cbf365c6af3e30d8c 100644
--- a/mutalyzer/website/templates/static/js/interface.js
+++ b/mutalyzer/website/templates/static/js/interface.js
@@ -52,6 +52,11 @@ $(document).ready(function() {
     event.stopPropagation();
   });
 
+  // Configure mailcheck.
+  //Mailcheck.defaultDomains.push('customdomain.com', 'anotherdomain.net');
+  //Mailcheck.defaultSecondLevelDomains.push('domain', 'yetanotherdomain');
+  Mailcheck.defaultTopLevelDomains.push('name', 'ac.uk', 'govt.nz', 'org.au');
+
   // Remove mailcheck suggestion for form element.
   var clearSuggestion = function(element) {
     $(element).siblings('.suggestion').remove();
diff --git a/mutalyzer/website/templates/static/js/mailcheck.min.js b/mutalyzer/website/templates/static/js/mailcheck.min.js
index 8019559db4bb7650279cb7a69df2e6b9dfa39c18..0c2fd97e30d5dced8af86e54a8a80b4a7ce20f5c 100644
--- a/mutalyzer/website/templates/static/js/mailcheck.min.js
+++ b/mutalyzer/website/templates/static/js/mailcheck.min.js
@@ -1,6 +1 @@
-/*1.1.0*/var Mailcheck={domainThreshold:4,topLevelThreshold:3,defaultDomains:"yahoo.com google.com hotmail.com gmail.com me.com aol.com mac.com live.com comcast.net googlemail.com msn.com hotmail.co.uk yahoo.co.uk facebook.com verizon.net sbcglobal.net att.net gmx.com mail.com outlook.com icloud.com".split(" "),defaultTopLevelDomains:"co.jp co.uk com net org info edu gov mil ca".split(" "),run:function(a){a.domains=a.domains||Mailcheck.defaultDomains;a.topLevelDomains=a.topLevelDomains||Mailcheck.defaultTopLevelDomains;
-a.distanceFunction=a.distanceFunction||Mailcheck.sift3Distance;var b=function(a){return a},c=a.suggested||b,b=a.empty||b;return(a=Mailcheck.suggest(Mailcheck.encodeEmail(a.email),a.domains,a.topLevelDomains,a.distanceFunction))?c(a):b()},suggest:function(a,b,c,d){a=a.toLowerCase();a=this.splitEmail(a);if(b=this.findClosestDomain(a.domain,b,d,this.domainThreshold)){if(b!=a.domain)return{address:a.address,domain:b,full:a.address+"@"+b}}else if(c=this.findClosestDomain(a.topLevelDomain,c,d,this.topLevelThreshold),
-a.domain&&c&&c!=a.topLevelDomain)return d=a.domain,b=d.substring(0,d.lastIndexOf(a.topLevelDomain))+c,{address:a.address,domain:b,full:a.address+"@"+b};return!1},findClosestDomain:function(a,b,c,d){d=d||this.topLevelThreshold;var e,g=99,f=null;if(!a||!b)return!1;c||(c=this.sift3Distance);for(var h=0;h<b.length;h++){if(a===b[h])return a;e=c(a,b[h]);e<g&&(g=e,f=b[h])}return g<=d&&null!==f?f:!1},sift3Distance:function(a,b){if(null==a||0===a.length)return null==b||0===b.length?0:b.length;if(null==b||
-0===b.length)return a.length;for(var c=0,d=0,e=0,g=0;c+d<a.length&&c+e<b.length;){if(a.charAt(c+d)==b.charAt(c+e))g++;else for(var f=e=d=0;5>f;f++){if(c+f<a.length&&a.charAt(c+f)==b.charAt(c)){d=f;break}if(c+f<b.length&&a.charAt(c)==b.charAt(c+f)){e=f;break}}c++}return(a.length+b.length)/2-g},splitEmail:function(a){a=a.trim().split("@");if(2>a.length)return!1;for(var b=0;b<a.length;b++)if(""===a[b])return!1;var c=a.pop(),d=c.split("."),e="";if(0==d.length)return!1;if(1==d.length)e=d[0];else{for(b=
-1;b<d.length;b++)e+=d[b]+".";2<=d.length&&(e=e.substring(0,e.length-1))}return{topLevelDomain:e,domain:c,address:a.join("@")}},encodeEmail:function(a){a=encodeURI(a);return a=a.replace("%20"," ").replace("%25","%").replace("%5E","^").replace("%60","`").replace("%7B","{").replace("%7C","|").replace("%7D","}")}};"undefined"!==typeof module&&module.exports&&(module.exports=Mailcheck);
-"undefined"!==typeof window&&window.jQuery&&function(a){a.fn.mailcheck=function(a){var c=this;if(a.suggested){var d=a.suggested;a.suggested=function(a){d(c,a)}}if(a.empty){var e=a.empty;a.empty=function(){e.call(null,c)}}a.email=this.val();Mailcheck.run(a)}}(jQuery);
+/*! mailcheck v1.1.1 @licence MIT */var Mailcheck={domainThreshold:2,secondLevelThreshold:2,topLevelThreshold:2,defaultDomains:["msn.com","bellsouth.net","telus.net","comcast.net","optusnet.com.au","earthlink.net","qq.com","sky.com","icloud.com","mac.com","sympatico.ca","googlemail.com","att.net","xtra.co.nz","web.de","cox.net","gmail.com","ymail.com","aim.com","rogers.com","verizon.net","rocketmail.com","google.com","optonline.net","sbcglobal.net","aol.com","me.com","btinternet.com","charter.net","shaw.ca"],defaultSecondLevelDomains:["yahoo","hotmail","mail","live","outlook","gmx"],defaultTopLevelDomains:["com","com.au","com.tw","ca","co.nz","co.uk","de","fr","it","ru","net","org","edu","gov","jp","nl","kr","se","eu","ie","co.il","us","at","be","dk","hk","es","gr","ch","no","cz","in","net","net.au","info","biz","mil","co.jp","sg","hu"],run:function(a){a.domains=a.domains||Mailcheck.defaultDomains,a.secondLevelDomains=a.secondLevelDomains||Mailcheck.defaultSecondLevelDomains,a.topLevelDomains=a.topLevelDomains||Mailcheck.defaultTopLevelDomains,a.distanceFunction=a.distanceFunction||Mailcheck.sift3Distance;var b=function(a){return a},c=a.suggested||b,d=a.empty||b,e=Mailcheck.suggest(Mailcheck.encodeEmail(a.email),a.domains,a.secondLevelDomains,a.topLevelDomains,a.distanceFunction);return e?c(e):d()},suggest:function(a,b,c,d,e){a=a.toLowerCase();var f=this.splitEmail(a);if(c&&d&&-1!==c.indexOf(f.secondLevelDomain)&&-1!==d.indexOf(f.topLevelDomain))return!1;var g=this.findClosestDomain(f.domain,b,e,this.domainThreshold);if(g)return g==f.domain?!1:{address:f.address,domain:g,full:f.address+"@"+g};var h=this.findClosestDomain(f.secondLevelDomain,c,e,this.secondLevelThreshold),i=this.findClosestDomain(f.topLevelDomain,d,e,this.topLevelThreshold);if(f.domain){var g=f.domain,j=!1;if(h&&h!=f.secondLevelDomain&&(g=g.replace(f.secondLevelDomain,h),j=!0),i&&i!=f.topLevelDomain&&(g=g.replace(f.topLevelDomain,i),j=!0),1==j)return{address:f.address,domain:g,full:f.address+"@"+g}}return!1},findClosestDomain:function(a,b,c,d){d=d||this.topLevelThreshold;var e,f=99,g=null;if(!a||!b)return!1;c||(c=this.sift3Distance);for(var h=0;h<b.length;h++){if(a===b[h])return a;e=c(a,b[h]),f>e&&(f=e,g=b[h])}return d>=f&&null!==g?g:!1},sift3Distance:function(a,b){if(null==a||0===a.length)return null==b||0===b.length?0:b.length;if(null==b||0===b.length)return a.length;for(var c=0,d=0,e=0,f=0,g=5;c+d<a.length&&c+e<b.length;){if(a.charAt(c+d)==b.charAt(c+e))f++;else{d=0,e=0;for(var h=0;g>h;h++){if(c+h<a.length&&a.charAt(c+h)==b.charAt(c)){d=h;break}if(c+h<b.length&&a.charAt(c)==b.charAt(c+h)){e=h;break}}}c++}return(a.length+b.length)/2-f},splitEmail:function(a){var b=a.trim().split("@");if(b.length<2)return!1;for(var c=0;c<b.length;c++)if(""===b[c])return!1;var d=b.pop(),e=d.split("."),f="",g="";if(0==e.length)return!1;if(1==e.length)g=e[0];else{f=e[0];for(var c=1;c<e.length;c++)g+=e[c]+".";g=g.substring(0,g.length-1)}return{topLevelDomain:g,secondLevelDomain:f,domain:d,address:b.join("@")}},encodeEmail:function(a){var b=encodeURI(a);return b=b.replace("%20"," ").replace("%25","%").replace("%5E","^").replace("%60","`").replace("%7B","{").replace("%7C","|").replace("%7D","}")}};"undefined"!=typeof module&&module.exports&&(module.exports=Mailcheck),"function"==typeof define&&define.amd&&define("mailcheck",[],function(){return Mailcheck}),"undefined"!=typeof window&&window.jQuery&&!function(a){a.fn.mailcheck=function(a){var b=this;if(a.suggested){var c=a.suggested;a.suggested=function(a){c(b,a)}}if(a.empty){var d=a.empty;a.empty=function(){d.call(null,b)}}a.email=this.val(),Mailcheck.run(a)}}(jQuery);
\ No newline at end of file