How to used Zimbra API ?

Have a great idea for extending Zimbra? Share ideas, ask questions, contribute, and get feedback.
thang-mt
Posts: 14
Joined: Mon Jan 17, 2022 2:05 pm

Re: How to used Zimbra API ?

Post by thang-mt »

Dear jeastman
When I try your above method to push the file to /service/upload path but I get 401 error, I don't know where I went wrong please help me.
I send you the command I execute and the content of the file login_cookies

Code: Select all

[admin2@mail ~]$ curl -k -X POST -b login_cookies -H "Content-Type: text/html" -H "Content-Disposition: attachment: filename=\'table3.html\'" -d @table3.html https://mail.baovietbank.local/service/upload
<html><head><script language='javascript'>
function doit() { window.parent._uploadManager.loaded(401,'null'); }
</script></head><body onload='doit()'></body></html>

Code: Select all

[admin2@mail ~]$ cat login_cookies
{
   "Header":{
      "context":{
         "change":{
            "token":639
         },
         "_jsns":"urn:zimbra"
      }
   },
   "Body":{
      "AuthResponse":{
         "authToken":[
            {
               "_content":"[redacted]"
            }
         ],
         "lifetime":172799998,
         "skin":[
            {
               "_content":"harmony"
            }
         ],
         "_jsns":"urn:zimbraAccount"
      }
   },
   "_jsns":"urn:zimbraSoap"
}
Edit: Please be careful not to post auth tokens, even if the hostname says local. People can figure it out. -jholder
thang-mt
Posts: 14
Joined: Mon Jan 17, 2022 2:05 pm

Re: How to used Zimbra API ?

Post by thang-mt »

jeastman wrote:
But I don't know how to generate the id of the file? The URL you sent me is very confusing, you give a variable but I don't understand how that variable is used to generate the id of the file.
From the referenced post:
To upload the file, you actually call the FileUploadServlet. This is not a SOAP request, just a POST to the appropriate URL with the content. You will need to specify a couple of things with the request.

ZM_AUTH_TOKEN - in the cookie HTTP header on the request.
CONTENT_TYPE - CONTENT_TYPE HTTP header
CONTENT_DISPOSITION - CONTENT_DISPOSITION HTTP header with "attachment: filename="myfile.txt"" fo the value.

This will return a plain text string with the ID of the uploaded content.
You will need to POST the contents of your file to the FileUploadServlet (http://example.com/service/upload) with ZM_AUTH_TOKEN (in Cookie), CONTENT_TYPE, and CONTENT_DISPOSITION set as HTTP headers on the POST request. This will return the ID for you to use in the SendMessageRequest as previously noted. The ZM_AUTH_TOKEN will already be set in a cookie as part of an AuthRequest.

Using curl (assuming the auth token is in "login_cookies" file - see original "Step 1 - obtain a Zimbra Auth Token") to upload "myfile.html" this would be:

Code: Select all

curl -X POST -b login_cookies -H "Content-Type: text/html" -H "Content-Disposition: attachment: filename=\"myfile.html\"" -d @myfile.html https://example.com/service/upload
When I try your above method to push the file to /service/upload path but I get 401 error, I don't know where I went wrong please help me.
I send you the command I execute and the content of the file login_cookies

Code: Select all

[admin2@mail ~]$ curl -k -X POST -b login_cookies -H "Content-Type: text/html" -H "Content-Disposition: attachment: filename=\'table3.html\'" -d @table3.html https://mail.baovietbank.local/service/upload
<html><head><script language='javascript'>
function doit() { window.parent._uploadManager.loaded(401,'null'); }
</script></head><body onload='doit()'></body></html>

Code: Select all

[admin2@mail ~]$ cat login_cookies
{
   "Header":{
      "context":{
         "change":{
            "token":639
         },
         "_jsns":"urn:zimbra"
      }
   },
   "Body":{
      "AuthResponse":{
         "authToken":[
            {
               "_content":"[redacted]"
            }
         ],
         "lifetime":172799998,
         "skin":[
            {
               "_content":"harmony"
            }
         ],
         "_jsns":"urn:zimbraAccount"
      }
   },
   "_jsns":"urn:zimbraSoap"
}
thang-mt
Posts: 14
Joined: Mon Jan 17, 2022 2:05 pm

Re: How to used Zimbra API ?

Post by thang-mt »

jeastman wrote:
But I don't know how to generate the id of the file? The URL you sent me is very confusing, you give a variable but I don't understand how that variable is used to generate the id of the file.
From the referenced post:
To upload the file, you actually call the FileUploadServlet. This is not a SOAP request, just a POST to the appropriate URL with the content. You will need to specify a couple of things with the request.

ZM_AUTH_TOKEN - in the cookie HTTP header on the request.
CONTENT_TYPE - CONTENT_TYPE HTTP header
CONTENT_DISPOSITION - CONTENT_DISPOSITION HTTP header with "attachment: filename="myfile.txt"" fo the value.

This will return a plain text string with the ID of the uploaded content.
You will need to POST the contents of your file to the FileUploadServlet (http://example.com/service/upload) with ZM_AUTH_TOKEN (in Cookie), CONTENT_TYPE, and CONTENT_DISPOSITION set as HTTP headers on the POST request. This will return the ID for you to use in the SendMessageRequest as previously noted. The ZM_AUTH_TOKEN will already be set in a cookie as part of an AuthRequest.

Using curl (assuming the auth token is in "login_cookies" file - see original "Step 1 - obtain a Zimbra Auth Token") to upload "myfile.html" this would be:

Code: Select all

curl -X POST -b login_cookies -H "Content-Type: text/html" -H "Content-Disposition: attachment: filename=\"myfile.html\"" -d @myfile.html https://example.com/service/upload
Also, I have an error

Code: Select all

[admin2@mail ~]$ curl -k -X POST -b login_cookie2 -H "Content-Type: text/html" -H "Content-Disposition: attachment: filename=\"/home/admin2/table3.html\"" -d @table3.html https://mail.baovietbank.local/service/upload
<html><head><script language='javascript'>
function doit() { window.parent._uploadManager.loaded(204,'null'); }
</script></head><body onload='doit()'></body></html>
User avatar
jeastman
Zimbra Employee
Zimbra Employee
Posts: 86
Joined: Tue Mar 29, 2016 1:36 pm

Re: How to used Zimbra API ?

Post by jeastman »

There are some options you can pass to the upload servlet which I neglected to include in my example. My apologies for leaving that out.

In order to get just the upload ID back from the request, you need to add "fmt=raw" query string parameter. Otherwise, it formats a javascript block result useful in a browser application. You can find out additional information in the Zimbra server file upload documentation: https://github.com/Zimbra/zm-mailbox/bl ... upload.txt

The target URL for curl should have been:

Code: Select all

https://example.com/service/upload?fmt=raw
So, the example should have been as follows:

Code: Select all

curl -X POST -b login_cookies -H "Content-Type: text/html" -H "Content-Disposition: attachment: filename=\"myfile.html\"" -d @myfile.html https://example.com/service/upload\?fmt\=raw
John Eastman
thang-mt
Posts: 14
Joined: Mon Jan 17, 2022 2:05 pm

Re: How to used Zimbra API ?

Post by thang-mt »

jeastman wrote:There are some options you can pass to the upload servlet which I neglected to include in my example. My apologies for leaving that out.

In order to get just the upload ID back from the request, you need to add "fmt=raw" query string parameter. Otherwise, it formats a javascript block result useful in a browser application. You can find out additional information in the Zimbra server file upload documentation: https://github.com/Zimbra/zm-mailbox/bl ... upload.txt

The target URL for curl should have been:

Code: Select all

https://example.com/service/upload?fmt=raw
So, the example should have been as follows:

Code: Select all

curl -X POST -b login_cookies -H "Content-Type: text/html" -H "Content-Disposition: attachment: filename=\"myfile.html\"" -d @myfile.html https://example.com/service/upload\?fmt\=raw
Dear jeastman
When i try it. I still get the old error of 204. Please help me.

Code: Select all

[admin2@mail ~]$ curl -v -k -X POST -b login_cookie2 -H "Content-Type: application/json" -H "Content-Disposition: attachment: filename=\"table3.html\"" -d @table3.html https://mail.baovietbank.local/service/upload\?fmt\=raw
* About to connect() to mail.baovietbank.local port 443 (#0)
*   Trying 10.33.130.100...
* Connected to mail.baovietbank.local (10.33.130.100) port 443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* skipping SSL peer certificate verification
* SSL connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
* Server certificate:
*       subject: CN=mail.baovietbank.local,OU=Zimbra Collaboration Server
*       start date: Jan 24 20:18:07 2022 GMT
*       expire date: Jan 23 20:18:07 2027 GMT
*       common name: mail.baovietbank.local
*       issuer: CN=mail.baovietbank.local,OU=Zimbra Collaboration Server,O=CA
> POST /service/upload?fmt=raw HTTP/1.1
> User-Agent: curl/7.29.0
> Host: mail.baovietbank.local
> Accept: */*
> Cookie: ZM_AUTH_TOKEN=[redacted]
> Content-Type: application/json
> Content-Disposition: attachment: filename="table3.html"
> Content-Length: 1414
> Expect: 100-continue
>
< HTTP/1.1 100 Continue
< HTTP/1.1 200 OK
< Server: nginx
< Date: Thu, 27 Jan 2022 13:12:32 GMT
< Content-Type: text/html;charset=utf-8
< Content-Length: 11
< Connection: keep-alive
< Vary: Accept-Encoding, User-Agent
<
204,'null'
* Connection #0 to host mail.baovietbank.local left intact

Code: Select all

[admin2@mail ~]$ curl -v -k -X POST -b login_cookies -H "Content-Type: text/html" -H "Content-Disposition: attachment: filename=\"table3.html\"" -d @table3.html https://mail.baovietbank.local/service/upload?fmt=raw
* About to connect() to mail.baovietbank.local port 443 (#0)
*   Trying 10.33.130.100...
* Connected to mail.baovietbank.local (10.33.130.100) port 443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* skipping SSL peer certificate verification
* SSL connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
* Server certificate:
*       subject: CN=mail.baovietbank.local,OU=Zimbra Collaboration Server
*       start date: Jan 24 20:18:07 2022 GMT
*       expire date: Jan 23 20:18:07 2027 GMT
*       common name: mail.baovietbank.local
*       issuer: CN=mail.baovietbank.local,OU=Zimbra Collaboration Server,O=CA
> POST /service/upload?fmt=raw HTTP/1.1
> User-Agent: curl/7.29.0
> Host: mail.baovietbank.local
> Accept: */*
> Cookie: ZM_AUTH_TOKEN=[redacted]
> Content-Type: text/html
> Content-Disposition: attachment: filename="table3.html"
> Content-Length: 1414
> Expect: 100-continue
>
< HTTP/1.1 100 Continue
< HTTP/1.1 200 OK
< Server: nginx
< Date: Thu, 27 Jan 2022 13:29:51 GMT
< Content-Type: text/html;charset=utf-8
< Content-Length: 11
< Connection: keep-alive
< Vary: Accept-Encoding, User-Agent
<
204,'null'
* Connection #0 to host mail.baovietbank.local left intact
Edit: Please be careful not to post auth tokens, even if the hostname says local. People can figure it out. -jholder
User avatar
jeastman
Zimbra Employee
Zimbra Employee
Posts: 86
Joined: Tue Mar 29, 2016 1:36 pm

Re: How to used Zimbra API ?

Post by jeastman »

Looking at the FileUploadServlet code, it seems the only time a 204 is returned (when there is actually some content) is when the filename is not specified (see https://github.com/Zimbra/zm-mailbox/bl ... .java#L737). Make sure the content disposition header is correct. It should be

Code: Select all

-H "Content-Type: application/json" -H "Content-Disposition: attachment; filename=\"table3.html\""
Pay attention to the ";" between the "attachment" and "filename", not ":". (That could have been mis-keyed in my example.) I am guessing this is the cause of the problem.

If that does not fix the problem, there are a couple of things you should check to resolve the 204 status code you are receiving:

1. Make sure the file you reference with the -d option ("table3.html") is correct. If the path is not correct or the file is empty, this could happen.
2. Check your server logs for any errors. There is pretty good logging in the FileUploadServlet, so you should see your problem.
John Eastman
thang-mt
Posts: 14
Joined: Mon Jan 17, 2022 2:05 pm

Re: How to used Zimbra API ?

Post by thang-mt »

jeastman wrote:Looking at the FileUploadServlet code, it seems the only time a 204 is returned (when there is actually some content) is when the filename is not specified (see https://github.com/Zimbra/zm-mailbox/bl ... .java#L737). Make sure the content disposition header is correct. It should be

Code: Select all

-H "Content-Type: application/json" -H "Content-Disposition: attachment; filename=\"table3.html\""
Pay attention to the ";" between the "attachment" and "filename", not ":". (That could have been mis-keyed in my example.) I am guessing this is the cause of the problem.

If that does not fix the problem, there are a couple of things you should check to resolve the 204 status code you are receiving:

1. Make sure the file you reference with the -d option ("table3.html") is correct. If the path is not correct or the file is empty, this could happen.
2. Check your server logs for any errors. There is pretty good logging in the FileUploadServlet, so you should see your problem.
Dear jeastman
Thank you. I have id file.
But I can't send mail with:

Code: Select all

 "SendMsgRequest": {
    "_jsns_": "urn:zimbraMail",
    "m": [{id: "505757"}]
  }
How is add the receiver and the sender?
Thank.
User avatar
jeastman
Zimbra Employee
Zimbra Employee
Posts: 86
Joined: Tue Mar 29, 2016 1:36 pm

Re: How to used Zimbra API ?

Post by jeastman »

How is add the receiver and the sender?
You use the attributes of the SendMsgRequest. Have a look at the documentation (https://files.zimbra.com/docs/soap_api/ ... ndMsg.html). The section at the top describes the different components.

Specifically, for the addressees by using the <e> element of the <m> element.
* Supports (f)rom, (t)o, (c)c, (b)cc, (r)eply-to, (s)ender, read-receipt (n)otification "type" on <e> elements.
There is an example of this earlier in this thread.

You can utilize the content ID you received from the FileUploadServlet as the value for any element which supports an ID (e.g. aid of attach element, id of m element, etc).
John Eastman
thang-mt
Posts: 14
Joined: Mon Jan 17, 2022 2:05 pm

Re: How to used Zimbra API ?

Post by thang-mt »

jeastman wrote:
How is add the receiver and the sender?
You use the attributes of the SendMsgRequest. Have a look at the documentation (https://files.zimbra.com/docs/soap_api/ ... ndMsg.html). The section at the top describes the different components.

Specifically, for the addressees by using the <e> element of the <m> element.
* Supports (f)rom, (t)o, (c)c, (b)cc, (r)eply-to, (s)ender, read-receipt (n)otification "type" on <e> elements.
There is an example of this earlier in this thread.

You can utilize the content ID you received from the FileUploadServlet as the value for any element which supports an ID (e.g. aid of attach element, id of m element, etc).
Dear jeastman
Is such content correct?

Code: Select all

 "SendMsgRequest": {
    "_jsns": "urn:zimbraMail",
    "m":  [{"id": "xxxxx"}],
    "su": "An example email",
        "e": [
          {
            "a": "FROM_ADDRESS@example.com",
            "t": "f"
          },
          {
            "a": "TO_ADDRESS@example.com",
            "t": "t"
          }
        ]
  }
when i send with this content, it is no get content form file my html
result to display

Code: Select all

{"Header":{"context":{"change":{"token":4623},"_jsns":"urn:zimbra"}},"Body":{"Fault":{"Code":{"Value":"soap:Sender"},"Reason":{"Text":"SMTP server reported: No recipient addresses"},"Detail":{"Error":{"Code":"mail.SEND_FAILURE","Trace":"qtp2076287037-48850:1644331332009:181f582faf258d11","_jsns":"urn:zimbra"}}}},"_jsns":"urn:zimbraSoap"}
Can you have example? Thanks
User avatar
jholder
Ambassador
Ambassador
Posts: 4824
Joined: Fri Sep 12, 2014 10:00 pm

Re: How to used Zimbra API ?

Post by jholder »

thang-mt wrote: when i send with this content, it is no get content form file my html
result to display

Code: Select all

{"Header":{"context":{"change":{"token":4623},"_jsns":"urn:zimbra"}},"Body":{"Fault":{"Code":{"Value":"soap:Sender"},"Reason":{"Text":"SMTP server reported: No recipient addresses"},"Detail":{"Error":{"Code":"mail.SEND_FAILURE","Trace":"qtp2076287037-48850:1644331332009:181f582faf258d11","_jsns":"urn:zimbra"}}}},"_jsns":"urn:zimbraSoap"}
Can you have example? Thanks
Maybe this will help:

Code: Select all

  "Body": {
    "SendMsgRequest": {
      "_jsns": "urn:zimbraMail",
      "suid": 1645083200491,
      "m": {
        "id": "xx",
        "did": "xxx",
        "idnt": "xx-xx-xxx",
        "e": [
          {
            "t": "t",
            "a": "TO_ADDR@synacor.com"
          },
          {
            "t": "f",
            "a": "jholder@zimbra.com",
            "p": "John  Holder"
          }
        ],
        "su": {
          "_content": "[MY HTML CONTENT]"
        },
        "mp": [
          {
            "ct": "multipart/alternative",
            "mp": [
              {
                "ct": "text/plain",
                "content": {
                  "_content": "[MY PLAINTEXT CONTENT]"
                }
              },
              {
                "ct": "text/html",
                "content": {
                  "_content": "BODY"
                }
              }
            ]
          }
        ]
      }
    }
  }
}
Post Reply