Skip to main content

Python SDK for Signic email - sign in with Ethereum, read and manage emails

Project description

signic-sdk

Python SDK for the Signic decentralized email platform. Authenticate with an Ethereum wallet via SIWE (Sign-In with Ethereum) and read emails from a WildDuck mail server.

Installation

pip install signic-sdk

Requirements: Python >= 3.11

Quick Start

import asyncio
from signic_sdk import SignicClient, SignicClientConfig

async def main():
    config = SignicClientConfig(
        private_key="0xac09...",
        indexer_url="https://api.signic.email/idx",
        wildduck_url="https://api.signic.email/api",
    )

    async with SignicClient(config) as client:
        # Derive addresses (no auth needed)
        print(client.get_address())       # "0xf39F..."
        print(client.get_email_address()) # "0xf39F...@signic.email"

        # Authenticate via SIWE
        await client.connect()

        # Fetch unread emails
        result = await client.get_unread_emails(10)
        print(f"{result.total} unread emails")

        # Get full email content
        full = await client.get_email(result.emails[0].id)
        print(full.subject, full.text)

        # Mark as read
        await client.mark_as_read(result.emails[0].id)

asyncio.run(main())

API Reference

SignicClient(config)

Create a new client instance.

Parameter Type Required Description
private_key str Yes EVM private key (hex with 0x prefix)
indexer_url str Yes Indexer API base URL
wildduck_url str Yes WildDuck API base URL
email_domain str No Email domain (default: signic.email)
chain_id int No EVM chain ID for SIWE (default: 1)

Supports async with for automatic resource cleanup:

async with SignicClient(config) as client:
    await client.connect()
    ...
# httpx client is automatically closed

Or close manually:

client = SignicClient(config)
try:
    await client.connect()
    ...
finally:
    await client.aclose()

Methods

get_address() -> str

Returns the EVM wallet address derived from the private key. Does not require authentication.

get_email_address() -> str

Returns the Signic email address (e.g. 0xabc...@signic.email). Does not require authentication.

is_connected() -> bool

Returns True if connect() has completed successfully.

async connect() -> None

Authenticate with the Signic platform via SIWE. Must be called before any email methods.

Performs a 6-step flow:

  1. Fetch a SIWE message from the Indexer
  2. Sign the message with the wallet's private key
  3. Convert the signature to base64
  4. Verify the signature with the Indexer
  5. Authenticate with WildDuck to get an access token
  6. Locate the INBOX mailbox

Raises: SignicAuthError on auth failure, SignicNetworkError on network failure.

async get_unread_emails(limit: int = 50) -> UnreadEmailsResult

Fetch unread emails from the inbox. Returns summary objects (use get_email() for full content).

Parameter Type Default Description
limit int 50 Maximum number of emails to return

Returns: UnreadEmailsResult with .emails: list[SignicEmail] and .total: int

async get_email(email_id: int, mailbox_id: str | None = None) -> SignicEmailDetail

Fetch the complete email by ID, including HTML/text body, all recipients, attachments, and flags.

Parameter Type Default Description
email_id int - Message UID from SignicEmail.id
mailbox_id str | None INBOX Mailbox to fetch from

Returns: SignicEmailDetail with html, text, cc, bcc, reply_to, attachments, verification_results, and all message flags.

async mark_as_read(message_id: int, mailbox_id: str | None = None) -> MarkAsReadResult

Mark a message as read (sets the \Seen flag).

Parameter Type Default Description
message_id int - Message UID
mailbox_id str | None INBOX Mailbox containing the message

Returns: MarkAsReadResult with .success: bool and .updated: int

async aclose() -> None

Close the underlying HTTP client. Called automatically when using async with.

Types

All types are frozen dataclasses.

SignicEmail

Summary email object returned by get_unread_emails().

@dataclass(frozen=True)
class SignicEmail:
    id: int                           # Message UID
    mailbox_id: str                   # Mailbox ID
    from_: SignicEmailAddress         # Sender (from_ because from is reserved)
    to: list[SignicEmailAddress]      # Recipients
    subject: str                      # Subject line
    date: str                         # ISO 8601 date
    intro: str                        # Preview (~128 chars)
    seen: bool                        # Read status
    has_attachments: bool             # Has file attachments

SignicEmailDetail

Full email object returned by get_email().

@dataclass(frozen=True)
class SignicEmailDetail:
    id: int
    mailbox_id: str
    thread: str                                     # Conversation thread ID
    from_: SignicEmailAddress
    to: list[SignicEmailAddress]
    cc: list[SignicEmailAddress]
    bcc: list[SignicEmailAddress]
    subject: str
    message_id: str                                 # Message-ID header
    date: str                                       # Date header (ISO 8601)
    idate: str                                      # Server receive date (ISO 8601)
    size: int                                       # Size in bytes
    seen: bool
    flagged: bool
    deleted: bool
    draft: bool
    answered: bool
    forwarded: bool
    html: list[str]                                 # HTML body parts
    text: str                                       # Plain text body
    attachments: list[SignicEmailAttachment]         # File attachments
    reply_to: SignicEmailAddress | None = None
    verification_results: VerificationResults | None = None

SignicEmailAttachment

@dataclass(frozen=True)
class SignicEmailAttachment:
    id: str                # Attachment ID
    hash: str              # SHA-256 hash (hex)
    filename: str          # Original filename
    content_type: str      # MIME type
    disposition: str       # "attachment" or "inline"
    transfer_encoding: str # Transfer encoding
    related: bool          # Inline/embedded image
    size_kb: int           # Approximate size in KB

Error Classes

All errors extend SignicError which carries operation and status_code attributes.

Error When
SignicError Base class for all SDK errors
SignicAuthError Authentication failure (401/403) or calling methods before connect()
SignicNetworkError Network failure (DNS, timeout, no response)
SignicValidationError Input validation failure (400/422)
from signic_sdk import SignicError, SignicAuthError

try:
    await client.get_unread_emails()
except SignicAuthError as err:
    print(f"Auth failed: {err.operation} {err.status_code}")
except SignicError as err:
    print(f"SDK error: {err}")

License

BUSL-1.1

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

signic_sdk-0.1.3.tar.gz (16.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

signic_sdk-0.1.3-py3-none-any.whl (13.3 kB view details)

Uploaded Python 3

File details

Details for the file signic_sdk-0.1.3.tar.gz.

File metadata

  • Download URL: signic_sdk-0.1.3.tar.gz
  • Upload date:
  • Size: 16.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for signic_sdk-0.1.3.tar.gz
Algorithm Hash digest
SHA256 33fc5ed15bc295aec4a3f6977f59d1b47b82271aa370220eb9ff41711799b906
MD5 a6644b07b323d912d04fb238dc3ee862
BLAKE2b-256 6be2f633ec9af5695cc40c27fd1ce36a8490fe8919a787aedbaa59744b98585b

See more details on using hashes here.

File details

Details for the file signic_sdk-0.1.3-py3-none-any.whl.

File metadata

  • Download URL: signic_sdk-0.1.3-py3-none-any.whl
  • Upload date:
  • Size: 13.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for signic_sdk-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 4a49b671d79f7bffced99b738a2525c4bf61c4ba878839d6e4e9323b308f3ff0
MD5 05569a623b80198e783ff46cbbb82e7a
BLAKE2b-256 d62c61633a764e2168542aa6f09537f153f14f7109ba9bad65685c6b91f5f772

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page