Files
JetCore/__imapaccounts.h
Brad ArantandClaude Sonnet 5 b8f7793773 Add global music player, invoicing/payment system, account subpages, mail account admin, and the qualityiron.vegas Jet 2.0 port
Jet interpreter (Tag.cpp, __call.cpp, __imap*.cpp/h, __smtpsend.cpp/h,
__imapemptyfolder.cpp/h - new): assorted parser/tag fixes found across
this work - a stray literal-tag-in-comment and backslash-quote parser
corruption class, a dangling-pointer fix, a __call.cpp fd leak, IMAP
folder-management tags, multi-account/per-host IMAP support, and a
smtpsend Message-ID fix.

barant.com site (jetc/barant-site/):
- A site-wide persistent music player (header band, playlist/queue,
  stereo FFT EQ, session-persisted state) fed by new library/
  ianslibrary/music song-list subpages.
- /account split into info/phones/invoices subpages; a full invoicing
  and Square payment system (create/edit/copy/pay/email invoice);
  admin invoice management and mail-account management subpages.
- /services split into overview/hosting/siptrunking/documents
  subpages, retiring the old standalone pages.
- SIPPHONE.tag: a Jet 2.0 WebRTC softphone tag.
- main.css/spa.js/email.js: the SPA loading indicator, the music
  player band styling, and assorted fixes accumulated alongside this
  work.

qualityiron-site/: the qualityiron.vegas job/contractor/customer/
document management app, ported from its original Jet 1.4 codebase to
Jet 2.0 as barant.coms APIServers second multi-tenant site.

wcwc/wcwc.jet: the WCWC site Jet source (wcwc.jtc build output not
included).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-06 17:42:01 +00:00

71 lines
2.9 KiB
C++

#ifndef ____imapaccounts_h__
# define ____imapaccounts_h__
# include "Tag.h"
# include "ZString.h"
# include "MString.h"
# include <string>
# include <utility>
# include <vector>
namespace jet {
///
/// <imapaccounts action="add|remove|getpassword|gethost|firstuser|list"
/// list="$[@_imap_accounts]" host="..." user="..." password="...">
///
/// Pure list-transform tag (no session-variable access of its own,
/// no IMAP connection) that manages the multi-account list webmail
/// keeps in the single session variable "_imap_accounts" - the .jet
/// route wraps each call in <eval name="_imap_accounts"> itself and
/// <set>s it back, the same separation-of-concerns every other
/// session variable in this codebase already uses (this tag never
/// touches Global's session-variable map directly).
///
/// The list's own on-the-wire encoding (semicolon-separated
/// "base64(host):base64(user):base64(password)" entries) is private
/// to this tag - callers only ever pass the whole `list` value back
/// in verbatim and use the returned value the same way, so the
/// choice of delimiter can't collide with any real username or
/// password character. Each account can live on its own IMAP server
/// (see the <imap>/<imaplist>/etc. tags' own optional host/port
/// keywords), not just the one fixed host in email.cfg.
///
/// action="add": upserts host/user/password (removing any existing
/// entry for the same user first, so reconnecting with a changed
/// password or server updates it) - returns the updated encoded list.
/// action="remove": drops the entry for user, if present - returns
/// the updated encoded list.
/// action="getpassword": returns the stored password for user, or
/// an empty string if not present.
/// action="gethost": returns the stored host for user, or an empty
/// string if not present.
/// action="firstuser": returns the first entry's username, or an
/// empty string if the list is empty.
/// action="list": returns JSON ({"accounts":[...],"active":"..."})
/// - the one client-facing action; "active" echoes the `active`
/// keyword (typically $[@_imap_user]) back verbatim so the sidebar
/// can highlight the current one, and never includes any password or
/// host (unchanged shape from before per-account hosts existed -
/// nothing client-side needs the host to switch between already-
/// connected accounts).
///
class __imapaccounts : public Tag {
struct Account {
std::string host, user, password;
};
public:
__imapaccounts(coreutils::ZString &in, coreutils::MString &parentOut, Global &global, Tag *parent, Tag *local);
private:
static std::vector<Account> decodeList(const std::string &encoded);
static std::string encodeList(const std::vector<Account> &entries);
static std::string jsonEscape(const std::string &s);
};
}
#endif