Awesome-omni-skill Zimbra API Integration
This skill should be used when the user asks about "SOAP API", "REST API", "Zimbra LDAP", "authentication token", "preauth", "ZCS API", "AdminService", "MailService", "zmsoap", or mentions programmatic access to Zimbra. Covers SOAP, REST, and LDAP interfaces for Zimbra integration.
install
source · Clone the upstream repo
git clone https://github.com/diegosouzapw/awesome-omni-skill
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/diegosouzapw/awesome-omni-skill "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/development/zimbra-api-integration" ~/.claude/skills/diegosouzapw-awesome-omni-skill-zimbra-api-integration && rm -rf "$T"
manifest:
skills/development/zimbra-api-integration/SKILL.mdsource content
Zimbra API Integration
Guide for integrating with Zimbra using SOAP API, REST API, and LDAP queries.
API Overview
Zimbra provides multiple integration interfaces:
| Interface | Use Case | Port |
|---|---|---|
| SOAP API | Full functionality, admin operations | 7071 (admin), 443 (user) |
| REST API | Calendar, contacts, documents | 443 |
| GraphQL | Modern web client (9.x+) | 443 |
| LDAP | Directory queries, provisioning | 389 |
SOAP API
Authentication
User Authentication
<!-- AuthRequest --> <soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"> <soap:Body> <AuthRequest xmlns="urn:zimbraAccount"> <account by="name">user@domain.com</account> <password>userpassword</password> </AuthRequest> </soap:Body> </soap:Envelope>
Response provides
authToken for subsequent requests.
Admin Authentication
<!-- Admin AuthRequest (port 7071) --> <soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"> <soap:Body> <AuthRequest xmlns="urn:zimbraAdmin"> <account by="name">admin@domain.com</account> <password>adminpassword</password> </AuthRequest> </soap:Body> </soap:Envelope>
Preauth (SSO)
Generate preauth token for seamless login:
import hashlib import hmac import time def generate_preauth(account, preauth_key, timestamp=None, expires=0): """Generate Zimbra preauth token""" if timestamp is None: timestamp = int(time.time() * 1000) # Format: account|by|expires|timestamp data = f"{account}|name|{expires}|{timestamp}" signature = hmac.new( preauth_key.encode(), data.encode(), hashlib.sha1 ).hexdigest() return { 'account': account, 'timestamp': timestamp, 'expires': expires, 'preauth': signature }
<!-- PreauthRequest --> <soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"> <soap:Body> <AuthRequest xmlns="urn:zimbraAccount"> <account by="name">user@domain.com</account> <preauth timestamp="1234567890000" expires="0">computed-signature</preauth> </AuthRequest> </soap:Body> </soap:Envelope>
Common SOAP Requests
Get Account Info
<GetAccountInfoRequest xmlns="urn:zimbraAccount"> <account by="name">user@domain.com</account> </GetAccountInfoRequest>
Search Messages
<SearchRequest xmlns="urn:zimbraMail" types="message" limit="100"> <query>in:inbox is:unread</query> </SearchRequest>
Send Message
<SendMsgRequest xmlns="urn:zimbraMail"> <m> <e t="t" a="recipient@domain.com"/> <su>Subject</su> <mp ct="text/plain"> <content>Message body</content> </mp> </m> </SendMsgRequest>
Create Appointment
<CreateAppointmentRequest xmlns="urn:zimbraMail"> <m> <inv> <comp name="Meeting"> <s d="20240115T100000" tz="America/New_York"/> <e d="20240115T110000" tz="America/New_York"/> </comp> </inv> <su>Team Meeting</su> </m> </CreateAppointmentRequest>
Using zmsoap
Command-line SOAP client:
# User request zmsoap -z -m user@domain.com GetInfoRequest # Admin request zmsoap -z -a admin@domain.com GetAllAccountsRequest # With specific namespace zmsoap -z -t account GetAccountInfoRequest @by=name @account=user@domain.com # Search zmsoap -z -m user@domain.com SearchRequest @types=message query "in:inbox"
REST API
URL Patterns
# Calendar (iCal) https://mail.domain.com/home/user@domain.com/calendar?fmt=ics # Contacts (vCard) https://mail.domain.com/home/user@domain.com/contacts?fmt=vcf # Briefcase files https://mail.domain.com/home/user@domain.com/Briefcase/file.pdf # Search results https://mail.domain.com/home/user@domain.com/?fmt=json&query=in:inbox
Authentication Methods
# Basic auth curl -u user@domain.com:password \ "https://mail.domain.com/home/user@domain.com/calendar?fmt=ics" # Auth token cookie curl -b "ZM_AUTH_TOKEN=authtoken" \ "https://mail.domain.com/home/user@domain.com/calendar" # Preauth URL curl "https://mail.domain.com/service/preauth?account=user@domain.com×tamp=...&preauth=..."
Common REST Operations
# Export calendar curl -u user:pass "https://mail/home/user/calendar?fmt=ics" > calendar.ics # Import contacts curl -u user:pass -X POST \ -H "Content-Type: text/vcard" \ --data-binary @contacts.vcf \ "https://mail/home/user/contacts" # Upload to Briefcase curl -u user:pass -X PUT \ --data-binary @document.pdf \ "https://mail/home/user/Briefcase/document.pdf" # Get folder structure curl -u user:pass "https://mail/home/user/?fmt=json&view=folder"
LDAP Integration
Connection Parameters
# Get LDAP password zmlocalconfig -s -m nokey zimbra_ldap_password # LDAP URL ldap://localhost:389 # Base DN zimbra
Common Queries
# Search all accounts ldapsearch -x -H ldap://localhost:389 \ -D "uid=zimbra,cn=admins,cn=zimbra" \ -w "$(zmlocalconfig -s -m nokey zimbra_ldap_password)" \ -b "ou=people,dc=domain,dc=com" \ "(objectClass=zimbraAccount)" # Find user by email ldapsearch -x -H ldap://localhost:389 \ -D "uid=zimbra,cn=admins,cn=zimbra" \ -w "$(zmlocalconfig -s -m nokey zimbra_ldap_password)" \ -b "" \ "(mail=user@domain.com)" # Get domain info ldapsearch -x -H ldap://localhost:389 \ -D "uid=zimbra,cn=admins,cn=zimbra" \ -w "$(zmlocalconfig -s -m nokey zimbra_ldap_password)" \ -b "dc=domain,dc=com" \ "(objectClass=zimbraDomain)"
Python LDAP Example
import ldap # Connect conn = ldap.initialize('ldap://zimbra-server:389') conn.simple_bind_s('uid=zimbra,cn=admins,cn=zimbra', ldap_password) # Search accounts results = conn.search_s( 'ou=people,dc=domain,dc=com', ldap.SCOPE_SUBTREE, '(objectClass=zimbraAccount)', ['mail', 'displayName', 'zimbraAccountStatus'] ) for dn, attrs in results: print(f"{attrs.get('mail', [b''])[0].decode()}: {attrs.get('displayName', [b''])[0].decode()}")
GraphQL API (9.x+)
Modern Web Client uses GraphQL:
# Endpoint: /graphql # Get folders query { getFolder { folders { id name unread } } } # Search messages query { search(query: "in:inbox", types: MESSAGE, limit: 50) { messages { id subject from { address } } } }
Error Handling
Common Error Codes
| Code | Meaning |
|---|---|
| Invalid credentials |
| Account not found |
| Insufficient permissions |
| Folder not found |
| Mailbox full |
Retry Logic
import time def make_soap_request(url, body, max_retries=3): for attempt in range(max_retries): try: response = requests.post(url, data=body, timeout=30) response.raise_for_status() return response except requests.exceptions.Timeout: if attempt < max_retries - 1: time.sleep(2 ** attempt) else: raise
Additional Resources
Reference Files
- Complete SOAP namespace documentationreferences/soap-api-reference.md
- Zimbra LDAP schema detailsreferences/ldap-schema.md
Example Files
- Python SOAP client wrapperexamples/soap-client.py
- Generate preauth tokensexamples/preauth-generator.py