Skip to main content
An actor that sends email gives every recipient their own unsubscribe link. A recipient has no wallet, so the link is the actor’s Gateway route: https://0x<actor>.<network>.cowboylabs.net/unsubscribe/<token>. cowboy_sdk.std.mail mints the tokens, serves the page and keeps the stop list.
How it behaves
  • Pass every address as address() returns it. The other functions key on the exact string, so " Ann@Example.com " and "ann@example.com" are different entries.
  • GET shows a confirmation page and changes nothing. Mail scanners prefetch links, and the Gateway runs a GET as a read.
  • POST (the page’s button, or a mail client’s RFC 8058 one-click request) spends the token and stops that one address.
  • A token is 32 hex characters hashed from the actor, the minting transaction, the address and a counter, so it cannot be derived from the address. Storage is public: anyone who reads it can use a token, and the worst case is an unwanted unsubscribe.
  • A stop is durable. enroll refuses a stopped address until the owner re-adds it with override=True. The stop list keeps only a hash of the address.
  • A replayed or unknown token changes nothing and gets the “may still arrive” page, so a replay never claims a cancellation.
Functions stopped(cancelled) answers “You are unsubscribed” only when every message already queued for the address is confirmed cancelled; otherwise it says one may still arrive. Storage keys are under unsub:: t:<token>, e:<email>, stop:<sha256(email)> and the counter n.