/api/qmail/poll

GET

Long-poll beacon endpoint. Blocks until new mail arrives or the specified timeout expires, providing an efficient way to receive real-time mail notifications without constant polling.

Description

The /api/qmail/poll endpoint implements a long-poll pattern for receiving real-time mail notifications. When called, the request blocks (holds the connection open) until either new mail arrives or the specified timeout period expires. This is far more efficient than repeatedly calling the quick-check endpoint.

Long-Poll Pattern

This endpoint is designed for:

  • Real-time mail notification systems
  • Efficient server-push-style updates over HTTP
  • Reducing network overhead compared to frequent short polling
  • Desktop and mobile clients that need instant new-mail alerts
Poll vs. Check

Unlike the /api/qmail/check endpoint which returns quickly with a 10-second timeout, this endpoint blocks for up to 10 minutes (600 seconds) by default. Use /poll when you want to be notified as soon as new mail arrives, and /check for quick non-blocking lookups.

Parameters

Parameter Type Required Description
timeout integer No Timeout in seconds for the long-poll. The request will block for at most this many seconds before returning. Default: 600. Maximum: 600 (10 minutes).

Response

Success Response Properties

success boolean
Indicates whether the poll completed successfully with new mail. true when new mail was found.
new_mail_count integer
The number of new mail notifications returned in this response.
total_remaining integer
The total number of notifications still remaining in the beacon queue after this response.
notifications array
Array of notification objects describing each new mail item.

Notification Object Properties

file_guid string
Hexadecimal GUID identifying the incoming file.
sender_sn integer
The serial number of the sender.
timestamp integer
Unix timestamp (in seconds) when the notification was created.
tell_type integer
Numeric type code indicating the kind of notification (e.g., message, file transfer).
total_file_size integer
Total size of the incoming file in bytes.

Error / Timeout Response Properties

success boolean
Will be false when the poll timed out or encountered an error.
message string
Human-readable description of what happened (e.g., "Poll timed out or failed").
error string
Machine-readable error code for programmatic handling.

Success Response Example (New Mail Arrived)

{
  "success": true,
  "new_mail_count": 3,
  "total_remaining": 7,
  "notifications": [
    {
      "file_guid": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6",
      "sender_sn": 14582,
      "timestamp": 1735689800,
      "tell_type": 1,
      "total_file_size": 2048
    },
    {
      "file_guid": "f6e5d4c3b2a1f6e5d4c3b2a1f6e5d4c3",
      "sender_sn": 28743,
      "timestamp": 1735689820,
      "tell_type": 1,
      "total_file_size": 15360
    },
    {
      "file_guid": "01234567890abcdef01234567890abcd",
      "sender_sn": 5091,
      "timestamp": 1735689845,
      "tell_type": 2,
      "total_file_size": 524288
    }
  ]
}

Timeout Response Example

{
  "success": false,
  "message": "Poll timed out or failed",
  "error": "poll_timeout"
}

Interactive API Tester

Test this Endpoint

http://localhost:8080/api/qmail/poll?timeout=30
Long-Running Request

This request will block until new mail arrives or the timeout expires. The default test timeout is set to 30 seconds. Adjust as needed.

Examples

cURL

# Long-poll with default 600-second timeout
curl "http://localhost:8080/api/qmail/poll"

# Long-poll with a custom 60-second timeout
curl "http://localhost:8080/api/qmail/poll?timeout=60"

JavaScript (fetch)

async function pollForMail(timeoutSeconds = 600) {
    const url = 'http://localhost:8080/api/qmail/poll'
        + `?timeout=${timeoutSeconds}`;

    // Set a client-side abort timeout slightly longer than the server timeout
    const controller = new AbortController();
    const clientTimeout = setTimeout(() => controller.abort(), (timeoutSeconds + 10) * 1000);

    try {
        const response = await fetch(url, { signal: controller.signal });
        const result = await response.json();

        if (result.success) {
            console.log(`New mail! ${result.new_mail_count} notification(s).`);
            console.log(`${result.total_remaining} more remaining in queue.`);
            result.notifications.forEach(n => {
                console.log(`  File: ${n.file_guid}, Sender SN: ${n.sender_sn}, Size: ${n.total_file_size} bytes`);
            });
        } else {
            console.log('Poll ended:', result.message);
        }

        return result;
    } catch (error) {
        if (error.name === 'AbortError') {
            console.log('Poll request timed out on client side.');
        } else {
            console.error('Poll error:', error);
        }
    } finally {
        clearTimeout(clientTimeout);
    }
}

// Continuous long-poll loop
async function startPolling() {
    while (true) {
        const result = await pollForMail(300);
        if (result && result.success) {
            // Process new mail notifications here
        }
        // Immediately re-poll (the server handles the wait)
    }
}

pollForMail(60);

Python

import requests

def poll_for_mail(timeout_seconds=600):
    """Long-poll for new mail notifications."""
    url = 'http://localhost:8080/api/qmail/poll'
    params = {'timeout': timeout_seconds}

    # Set a client-side timeout slightly longer than the server timeout
    response = requests.get(url, params=params, timeout=timeout_seconds + 10)
    result = response.json()

    if result['success']:
        print(f"New mail! {result['new_mail_count']} notification(s).")
        print(f"{result['total_remaining']} more remaining in queue.")
        for n in result['notifications']:
            print(f"  File: {n['file_guid']}, Sender SN: {n['sender_sn']}, Size: {n['total_file_size']} bytes")
    else:
        print(f"Poll ended: {result['message']}")

    return result

# Continuous long-poll loop
def start_polling():
    while True:
        try:
            result = poll_for_mail(timeout_seconds=300)
            if result['success']:
                # Process new mail notifications here
                pass
        except requests.exceptions.Timeout:
            print('Poll request timed out, restarting...')
        except requests.exceptions.RequestException as e:
            print(f'Poll error: {e}')

poll_for_mail(timeout_seconds=60)

Important Notes

Blocking Request

This is a long-poll endpoint. The HTTP connection remains open until new mail arrives or the timeout expires. Ensure your HTTP client is configured with an appropriate timeout that exceeds the server-side timeout parameter to avoid premature client-side disconnections.

Timeout Behavior

The timeout parameter controls how long the server will wait for new mail. The default and maximum value is 600 seconds (10 minutes). If no new mail arrives within the timeout, the server responds with success: false and the message "Poll timed out or failed". Simply re-issue the request to continue waiting.

Client Timeout Configuration

Always set your client-side HTTP timeout to be slightly longer than the server-side timeout value. For example, if you set timeout=300, configure your HTTP client to wait at least 310 seconds. This prevents the client from disconnecting before the server has a chance to respond.

Continuous Polling Pattern

For real-time notifications, implement a continuous loop: call /poll, process any results, then immediately call /poll again. The server handles the waiting, so there is no need to add a sleep delay between requests.