[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$f2t7JbVzkeG2UQ42RalWmc936srV8vM0KnAoNlZJUnQs":3},{"id":4,"question":5,"answer":6,"answerHtml":7,"slug":8,"keywords":9,"article":10,"status":33,"aiModel":30,"aiConfidence":30,"updatedAt":49,"createdAt":49,"_status":48},229,"How do I enable pre-authentication and generate a PreAuthKey in Zimbra?","Pre-authentication is disabled by default. To enable it, run the command `\u002Fopt\u002Fzimbra\u002Fbin\u002Fzmprov generateDomainPreAuthKey \u003Cdomain>` (replace `\u003Cdomain>` with your Zimbra domain, e.g., `mail.test.com`). This generates a PreAuthKey that you can later retrieve with `zmprov gd \u003Cdomain> zimbraPreAuthKey`. For a full example with sample output, refer to the pre-authentication section in the [Zimbra SOAP API Development Guide 6 - Pre-authentication](\u002Fnews\u002Fzimbra-soap-api-development-guide-6-pre-authentication1).","\u003Cp>Pre-authentication is disabled by default. To enable it, run the command `\u002Fopt\u002Fzimbra\u002Fbin\u002Fzmprov generateDomainPreAuthKey &lt;domain&gt;` (replace `&lt;domain&gt;` with your Zimbra domain, e.g., `mail.test.com`). This generates a PreAuthKey that you can later retrieve with `zmprov gd &lt;domain&gt; zimbraPreAuthKey`. For a full example with sample output, refer to the pre-authentication section in the [Zimbra SOAP API Development Guide 6 - Pre-authentication](\u002Fnews\u002Fzimbra-soap-api-development-guide-6-pre-authentication1).\u003C\u002Fp>\u003Cp>\u003Ca href=\"\u002Fnews\u002Fzimbra-soap-api-development-guide-6-pre-authentication1\">Read the related One Day Sec article\u003C\u002Fa>\u003C\u002Fp>","how-do-i-enable-pre-authentication-and-generate-a-preauthkey-in-zimbra-1777484586803","zmprov, generateDomainPreAuthKey, enable pre-authentication, PreAuthKey, Zimbra domain",{"id":11,"title":12,"slug":13,"description":14,"content":15,"contentHtml":27,"cover":30,"author":31,"views":19,"readingTime":32,"status":33,"publishedAt":34,"seo":35,"tags":39,"qaPairs":40,"meta":45,"updatedAt":46,"createdAt":47,"_status":48},60,"Zimbra SOAP API Development Guide 6 - Pre-authentication","zimbra-soap-api-development-guide-6-pre-authentication1","Learn to enable Zimbra pre-authentication, generate PreAuthKey, and implement SOAP login with Python code for secure mailbox access.",{"root":16},{"type":17,"format":18,"indent":19,"version":20,"children":21,"direction":29},"root","",0,1,[22],{"type":23,"format":18,"indent":19,"version":20,"children":24,"direction":29},"paragraph",[25],{"mode":26,"text":27,"type":28,"style":18,"detail":19,"format":19,"version":20},"normal","\u003Chtml>\u003Chead>\u003C\u002Fhead>\u003Cbody>\u003Ch2>0x00 Preface\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>This article will continue to expand the practical features of the open-source code Zimbra_SOAP_API_Manage by adding a pre-authentication login method, sharing development details.\u003C\u002Fp>\u003Ch2>0x01 Introduction\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>This article will cover the following topics:\u003C\u002Fp>\u003Cul>\u003Cli>Pre-authentication\u003C\u002Fli>\u003Cli>Calculating preauth\u003C\u002Fli>\u003Cli>SOAP implementation\u003C\u002Fli>\u003Cli>Open-source code\u003C\u002Fli>\u003C\u002Ful>\u003Ch2>0x02 Pre-authentication\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>Reference: https:\u002F\u002Fwiki.zimbra.com\u002Fwiki\u002FPreauth\u003C\u002Fp>\u003Cp>Simple explanation: Using preAuthKey combined with username, timestamp, and expiration time, the calculated HMAC serves as an authentication token, which can be used for user mailbox and SOAP login\u003C\u002Fp>\u003Cp>By default, Zimbra does not enable pre-authentication functionality and requires manual activation.\u003C\u002Fp>\u003Ch4>(1) Enable pre-authentication and generate PreAuthKey\u003C\u002Fh4>\u003Cp>The command is as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>\u002Fopt\u002Fzimbra\u002Fbin\u002Fzmrov generateDomainPreAuthKey \u003Cdomain>\u003C\u002Fdomain>\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Here, \u003Cdomain> corresponds to the current Zimbra server's domain name, which can be obtained by executing the command \u002Fopt\u002Fzimbra\u002Fbin\u002Fzmprov gad. The output in the test environment is as follows:\u003C\u002Fdomain>\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>mail.test.com\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>The corresponding command for the test environment is: \u002Fopt\u002Fzimbra\u002Fbin\u002Fzmprov generateDomainPreAuthKey mail.test.com\u003C\u002Fp>\u003Cp>The output in the test environment is as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>preAuthKey: fbf0ace37c59e3893352c656eda3d7f25c0ce0baadc9cbf22eb03f3b256f17a7\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch4>(2) Read existing PreAuthKey\u003C\u002Fh4>\u003Cp>The command is as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>\u002Fopt\u002Fzimbra\u002Fbin\u002Fzmprov gd \u003Cdomain> zimbraPreAuthKey\u003C\u002Fdomain>\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>The corresponding command for the test environment is: \u002Fopt\u002Fzimbra\u002Fbin\u002Fzmprov gd mail.test.com zimbraPreAuthKey\u003C\u002Fp>\u003Cp>The output in the test environment is as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>zimbraPreAuthKey: fbf0ace37c59e3893352c656eda3d7f25c0ce0baadc9cbf22eb03f3b256f17a7\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>If Zimbra has multiple domains, there will be multiple PreAuthKeys\u003C\u002Fp>\u003Ch2>0x03 Calculate preauth\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>The reference materials provide multiple examples of calculating preauth, but the Python implementation code is incomplete. Here, the complete implementation code under Python3 is supplemented, with detailed code as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>from time import time\u003Cbr>import hmac, hashlib\u003Cbr>import sys\u003Cbr>def generate_preauth(target, preauth_key, mailbox):\u003Cbr>    try:\u003Cbr>        preauth_url = target + \"\u002Fservice\u002Fpreauth\"\u003Cbr>        timestamp = int(time()*1000)\u003Cbr>        data = \"{mailbox}|name|0|{timestamp}\".format(mailbox=mailbox, timestamp=timestamp)\u003Cbr>        pak = hmac.new(preauth_key.encode(), data.encode(), hashlib.sha1).hexdigest()\u003Cbr>        print(\"[+] Preauth url: \")   \u003Cbr>        print(\"%s?account=%s&amp;expires=0×tamp=%s&amp;preauth=%s\"%(preauth_url, mailbox, timestamp, pak))\u003Cbr>    except Exception as e:\u003Cbr>        print(\"[!] Error:%s\"%(e))\u003Cbr>\u003Cbr>if __name__ == \"__main__\":\u003Cbr>    if len(sys.argv)!=4:\u003Cbr>        print('GeneratePreauth')\u003Cbr>        print('Use to generate the preauth key')\u003Cbr>        print('Usage:')\u003Cbr>        print('%s \u003Chost> \u003Cpreauth_key> \u003Cmailuser>'%(sys.argv[0])) \u003Cbr>        print('Eg.')\u003Cbr>        print('%s https:\u002F\u002F192.168.1.1 fbf0ace37c59e3893352c656eda3d7f25c0ce0baadc9cbf22eb03f3b256f17a7 test1@mail.test.com'%(sys.argv[0]))\u003Cbr>        sys.exit(0)\u003Cbr>    else:\u003Cbr>        generate_preauth(sys.argv[1], sys.argv[2], sys.argv[3])\u003C\u002Fmailuser>\u003C\u002Fpreauth_key>\u003C\u002Fhost>\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>The code will automatically generate a usable URL; accessing it via browser will log into the specified mailbox\u003C\u002Fp>\u003Ch2>0x04 SOAP Implementation\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>SOAP Format:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>\u003Cauthrequest xmlns=\"urn:zimbraAccount\">\u003Cbr>\u003Caccount by=\"name|id|foreignPrincipal\">{account-identifier}\u003C\u002Faccount>\u003Cbr>\u003Cpreauth timestamp=\"{timestamp}\" expires=\"{expires}\">{computed-preauth}\u003C\u002Fpreauth>\u003Cbr>\u003C\u002Fauthrequest>\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>SOAP Format Example:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>\u003Cauthrequest xmlns=\"urn:zimbraAccount\">\u003Cbr>\u003Caccount>john.doe@domain.com\u003C\u002Faccount>\u003Cbr>\u003Cpreauth timestamp=\"1135280708088\" expires=\"0\">b248f6cfd027edd45c5369f8490125204772f844\u003C\u002Fpreauth>\u003Cbr>\u003C\u002Fauthrequest>\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Requires timestamp and preauth as parameters. Detailed code for pre-authentication login is as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>import sys\u003Cbr>import requests\u003Cbr>import re\u003Cbr>import warnings\u003Cbr>warnings.filterwarnings(\"ignore\")\u003Cbr>from time import time\u003Cbr>import hmac, hashlib\u003Cbr>\u003Cbr>def generate_preauth(target, mailbox, preauth_key):\u003Cbr>    try:\u003Cbr>        preauth_url = target + \"\u002Fservice\u002Fpreauth\"\u003Cbr>        timestamp = int(time()*1000)\u003Cbr>        data = \"{mailbox}|name|0|{timestamp}\".format(mailbox=mailbox, timestamp=timestamp)\u003Cbr>        pak = hmac.new(preauth_key.encode(), data.encode(), hashlib.sha1).hexdigest()\u003Cbr>        print(\"[+] Preauth url: \")\u003Cbr>        print(\"%s?account=%s&amp;expires=0×tamp=%s&amp;preauth=%s\"%(preauth_url, mailbox, timestamp, pak))\u003Cbr>        return timestamp, pak\u003Cbr>    except Exception as e:\u003Cbr>        print(\"[!] Error:%s\"%(e))\u003Cbr>\u003Cbr>headers = {\u003Cbr>    \"User-Agent\": \"Mozilla\u002F5.0 (Windows NT 6.3; Win64; x64) AppleWebKit\u002F537.36 (KHTML, like Gecko) Chrome\u002F81.0.4044.129 Safari\u002F537.36\"\u003Cbr>}\u003Cbr>\u003Cbr>def auth_request_preauth(uri,username,timestamp,pak):\u003Cbr>    request_body=\"\"\"\u003Csoap:envelope xmlns:soap=\"http:\u002F\u002Fwww.w3.org\u002F2003\u002F05\u002Fsoap-envelope\">\u003Cbr>       \u003Csoap:header>\u003Cbr>           \u003Ccontext xmlns=\"urn:zimbra\">\u003Cbr>           \u003C\u002Fcontext>\u003Cbr>       \u003C\u002Fsoap:header>\u003Cbr>       \u003Csoap:body>\u003Cbr>         \u003Cauthrequest xmlns=\"urn:zimbraAccount\">\u003Cbr>            \u003Caccount>{username}\u003C\u002Faccount>\u003Cbr>            \u003Cpreauth timestamp=\"{timestamp}\" expires=\"0\">{pak}\u003C\u002Fpreauth>\u003Cbr>         \u003C\u002Fauthrequest>\u003Cbr>       \u003C\u002Fsoap:body>\u003Cbr>    \u003C\u002Fsoap:envelope>\u003Cbr>    \"\"\"\u003Cbr>    try:\u003Cbr>        r=requests.post(uri+\"\u002Fservice\u002Fsoap\",headers=headers,data=request_body.format(username=username,timestamp=timestamp,pak=pak),verify=False,timeout=15)\u003Cbr>        if 'authentication failed' in r.text:\u003Cbr>            print(\"[-] Authentication failed for %s\"%(username))\u003Cbr>            exit(0)\u003Cbr>        elif 'authToken' in r.text:\u003Cbr>            pattern_auth_token=re.compile(r\"\u003Cauthtoken>(.*?)\u003C\u002Fauthtoken>\")\u003Cbr>            token = pattern_auth_token.findall(r.text)[0]\u003Cbr>            print(\"[+] Authentication success for %s\"%(username))\u003Cbr>            print(\"[*] authToken_low:%s\"%(token))\u003Cbr>            return token\u003Cbr>        else:\u003Cbr>            print(\"[!]\")\u003Cbr>            print(r.text)\u003Cbr>    except Exception as e:\u003Cbr>        print(\"[!] Error:%s\"%(e))\u003Cbr>        exit(0)\u003Cbr>\u003Cbr>timestamp, pak = generate_preauth(\"https:\u002F\u002F192.168.1.1\", \"test1@mail.test.com\", \"fbf0ace37c59e3893352c656eda3d7f25c0ce0baadc9cbf22eb03f3b256f17a7\")\u003Cbr>token = auth_request_preauth(\"https:\u002F\u002F192.168.1.1\",\"test1@mail.test.com\",timestamp,pak)\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>The above code performs pre-authentication login and returns a usable token. Using this token, subsequent SOAP operations can be performed. Implementation code for listing folder email counts:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>def getfolder_request(uri,token):\u003Cbr>    request_body=\"\"\"\u003Csoap:envelope xmlns:soap=\"http:\u002F\u002Fwww.w3.org\u002F2003\u002F05\u002Fsoap-envelope\">\u003Cbr>       \u003Csoap:header>\u003Cbr>           \u003Ccontext xmlns=\"urn:zimbra\">\u003Cbr>               \u003Cauthtoken>{token}\u003C\u002Fauthtoken>\u003Cbr>           \u003C\u002Fcontext>\u003Cbr>       \u003C\u002Fsoap:header>\u003Cbr>       \u003Csoap:body>\u003Cbr>         \u003Cgetfolderrequest xmlns=\"urn:zimbraMail\"> \u003Cbr>         \u003C\u002Fgetfolderrequest>\u003Cbr>       \u003C\u002Fsoap:body>\u003Cbr>    \u003C\u002Fsoap:envelope>\u003Cbr>    \"\"\"\u003Cbr>    try:\u003Cbr>        print(\"[*] Try to get folder\")\u003Cbr>        r=requests.post(uri+\"\u002Fservice\u002Fsoap\",headers=headers,data=request_body.format(token=token),verify=False,timeout=15)\u003Cbr>        pattern_name = re.compile(r\"name=\\\"(.*?)\\\"\")\u003Cbr>        name = pattern_name.findall(r.text)\u003Cbr>        pattern_size = re.compile(r\" n=\\\"(.*?)\\\"\")\u003Cbr>        size = pattern_size.findall(r.text)\u003Cbr>        for i in range(len(name)):\u003Cbr>            print(\"[+] Name:%s,Size:%s\"%(name[i],size[i]))\u003Cbr>    except Exception as e:\u003Cbr>        print(\"[!] Error:%s\"%(e))\u003Cbr>\u003Cbr>getfolder_request(\"https:\u002F\u002F192.168.1.1\",token)\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch2>0x05 Open Source Code\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>New code has been uploaded to GitHub at the following address:\u003C\u002Fp>\u003Cp>An open source project\u003C\u002Fp>\u003Cp>Added functionality for using pre-authentication login\u003C\u002Fp>\u003Ch2>0x06 Summary\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>This article expands the Zimbra SOAP API invocation methods by adding functionality for using pre-authentication login.\u003C\u002Fp>\u003C\u002Fbody>\u003C\u002Fhtml>","text","ltr",null,"Onedaysec",3,"published","2026-02-02T08:07:45.499Z",{"title":36,"description":14,"keywords":37,"ogImage":30,"canonicalUrl":30,"noIndex":38},"Zimbra SOAP API Pre-authentication Guide: Enable & Implement","Zimbra SOAP API, pre-authentication, PreAuthKey, Python implementation, Zimbra login, SOAP development",false,[],{"docs":41,"hasNextPage":38},[42,43,4,44],231,230,228,{"title":30,"description":30,"image":30},"2026-07-24T02:07:27.647Z","2026-07-23T16:01:13.043Z","draft","2026-07-23T16:04:42.187Z"]