Skip to content

Commit 188bf45

Browse files
atergaclaude
andcommitted
feat: add Postbox tab to frontend and get_postbox query endpoint
- Add `get_postbox` query endpoint returning emails for an anchor number - Add `PostboxEmail` Candid type and regenerate frontend IDL/types - Change SMTP recipient format from hardcoded users to `anchor_number@id.ai` - Add Postbox nav tab (visible only when emails exist) with MailIcon - Create Postbox page with two-column layout: email list + email content - Load postbox data in authenticated layout alongside identity info Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 13b59e1 commit 188bf45

File tree

10 files changed

+446
-16
lines changed

10 files changed

+446
-16
lines changed

src/frontend/src/lib/generated/internet_identity_idl.js

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,21 @@ export const idlFactory = ({ IDL }) => {
352352
'no_such_delegation' : IDL.Null,
353353
'signed_delegation' : SignedDelegation,
354354
});
355+
const GetIcrc3AttributeRequest = IDL.Record({
356+
'origin' : FrontendHostname,
357+
'account_number' : IDL.Opt(AccountNumber),
358+
'message' : IDL.Vec(IDL.Nat8),
359+
'identity_number' : IdentityNumber,
360+
});
361+
const GetIcrc3AttributeResponse = IDL.Record({
362+
'signature' : IDL.Vec(IDL.Nat8),
363+
});
364+
const GetIcrc3AttributeError = IDL.Variant({
365+
'AuthorizationError' : IDL.Principal,
366+
'NoSuchSignature' : IDL.Null,
367+
'ValidationError' : IDL.Record({ 'problems' : IDL.Vec(IDL.Text) }),
368+
'GetAccountError' : GetAccountError,
369+
});
355370
const GetIdAliasRequest = IDL.Record({
356371
'rp_id_alias_jwt' : IDL.Text,
357372
'issuer' : FrontendHostname,
@@ -373,6 +388,12 @@ export const idlFactory = ({ IDL }) => {
373388
'Unauthorized' : IDL.Principal,
374389
'NoSuchCredentials' : IDL.Text,
375390
});
391+
const PostboxEmail = IDL.Record({
392+
'subject' : IDL.Text,
393+
'body' : IDL.Text,
394+
'recipient' : IDL.Text,
395+
'sender' : IDL.Text,
396+
});
376397
const HeaderField = IDL.Tuple(IDL.Text, IDL.Text);
377398
const HttpRequest = IDL.Record({
378399
'url' : IDL.Text,
@@ -442,6 +463,17 @@ export const idlFactory = ({ IDL }) => {
442463
'AlreadyInProgress' : IDL.Null,
443464
'RateLimitExceeded' : IDL.Null,
444465
});
466+
const ListAvailableAttributesRequest = IDL.Record({
467+
'attributes' : IDL.Opt(IDL.Vec(IDL.Text)),
468+
'identity_number' : IdentityNumber,
469+
});
470+
const ListAvailableAttributesResponse = IDL.Vec(
471+
IDL.Tuple(IDL.Text, IDL.Vec(IDL.Nat8))
472+
);
473+
const ListAvailableAttributesError = IDL.Variant({
474+
'AuthorizationError' : IDL.Principal,
475+
'ValidationError' : IDL.Record({ 'problems' : IDL.Vec(IDL.Text) }),
476+
});
445477
const DeviceKeyWithAnchor = IDL.Record({
446478
'pubkey' : DeviceKey,
447479
'anchor_number' : UserNumber,
@@ -497,6 +529,27 @@ export const idlFactory = ({ IDL }) => {
497529
'ValidationError' : IDL.Record({ 'problems' : IDL.Vec(IDL.Text) }),
498530
'GetAccountError' : GetAccountError,
499531
});
532+
const AttributeSpec = IDL.Record({
533+
'key' : IDL.Text,
534+
'value' : IDL.Opt(IDL.Vec(IDL.Nat8)),
535+
'omit_scope' : IDL.Bool,
536+
});
537+
const PrepareIcrc3AttributeRequest = IDL.Record({
538+
'origin' : FrontendHostname,
539+
'account_number' : IDL.Opt(AccountNumber),
540+
'attributes' : IDL.Vec(AttributeSpec),
541+
'nonce' : IDL.Vec(IDL.Nat8),
542+
'identity_number' : IdentityNumber,
543+
});
544+
const PrepareIcrc3AttributeResponse = IDL.Record({
545+
'message' : IDL.Vec(IDL.Nat8),
546+
});
547+
const PrepareIcrc3AttributeError = IDL.Variant({
548+
'AuthorizationError' : IDL.Principal,
549+
'ValidationError' : IDL.Record({ 'problems' : IDL.Vec(IDL.Text) }),
550+
'GetAccountError' : GetAccountError,
551+
'AttributeMismatch' : IDL.Record({ 'problems' : IDL.Vec(IDL.Text) }),
552+
});
500553
const PrepareIdAliasRequest = IDL.Record({
501554
'issuer' : FrontendHostname,
502555
'relying_party' : FrontendHostname,
@@ -530,6 +583,26 @@ export const idlFactory = ({ IDL }) => {
530583
'anchor_number' : UserNumber,
531584
}),
532585
});
586+
const SmtpAddress = IDL.Record({ 'domain' : IDL.Text, 'user' : IDL.Text });
587+
const SmtpEnvelope = IDL.Record({ 'to' : SmtpAddress, 'from' : SmtpAddress });
588+
const SmtpHeader = IDL.Record({ 'value' : IDL.Text, 'name' : IDL.Text });
589+
const SmtpMessage = IDL.Record({
590+
'body' : IDL.Vec(IDL.Nat8),
591+
'headers' : IDL.Vec(SmtpHeader),
592+
});
593+
const SmtpRequest = IDL.Record({
594+
'envelope' : IDL.Opt(SmtpEnvelope),
595+
'message' : IDL.Opt(SmtpMessage),
596+
'gateway_flags' : IDL.Opt(IDL.Vec(IDL.Text)),
597+
});
598+
const SmtpRequestError = IDL.Record({
599+
'code' : IDL.Nat64,
600+
'message' : IDL.Text,
601+
});
602+
const SmtpResponse = IDL.Variant({
603+
'Ok' : IDL.Record({}),
604+
'Err' : SmtpRequestError,
605+
});
533606
const ArchiveInfo = IDL.Record({
534607
'archive_config' : IDL.Opt(ArchiveConfig),
535608
'archive_canister' : IDL.Opt(IDL.Principal),
@@ -728,11 +801,22 @@ export const idlFactory = ({ IDL }) => {
728801
[GetDelegationResponse],
729802
['query'],
730803
),
804+
'get_icrc3_attributes' : IDL.Func(
805+
[GetIcrc3AttributeRequest],
806+
[
807+
IDL.Variant({
808+
'Ok' : GetIcrc3AttributeResponse,
809+
'Err' : GetIcrc3AttributeError,
810+
}),
811+
],
812+
['query'],
813+
),
731814
'get_id_alias' : IDL.Func(
732815
[GetIdAliasRequest],
733816
[IDL.Variant({ 'Ok' : IdAliasCredentials, 'Err' : GetIdAliasError })],
734817
['query'],
735818
),
819+
'get_postbox' : IDL.Func([UserNumber], [IDL.Vec(PostboxEmail)], ['query']),
736820
'get_principal' : IDL.Func(
737821
[UserNumber, FrontendHostname],
738822
[IDL.Principal],
@@ -780,6 +864,16 @@ export const idlFactory = ({ IDL }) => {
780864
[],
781865
),
782866
'init_salt' : IDL.Func([], [], []),
867+
'list_available_attributes' : IDL.Func(
868+
[ListAvailableAttributesRequest],
869+
[
870+
IDL.Variant({
871+
'Ok' : ListAvailableAttributesResponse,
872+
'Err' : ListAvailableAttributesError,
873+
}),
874+
],
875+
['query'],
876+
),
783877
'lookup' : IDL.Func([UserNumber], [IDL.Vec(DeviceData)], ['query']),
784878
'lookup_by_registration_mode_id' : IDL.Func(
785879
[RegistrationId],
@@ -862,6 +956,16 @@ export const idlFactory = ({ IDL }) => {
862956
[UserKey, Timestamp],
863957
[],
864958
),
959+
'prepare_icrc3_attributes' : IDL.Func(
960+
[PrepareIcrc3AttributeRequest],
961+
[
962+
IDL.Variant({
963+
'Ok' : PrepareIcrc3AttributeResponse,
964+
'Err' : PrepareIcrc3AttributeError,
965+
}),
966+
],
967+
[],
968+
),
865969
'prepare_id_alias' : IDL.Func(
866970
[PrepareIdAliasRequest],
867971
[IDL.Variant({ 'Ok' : PreparedIdAlias, 'Err' : PrepareIdAliasError })],
@@ -879,6 +983,12 @@ export const idlFactory = ({ IDL }) => {
879983
[IDL.Variant({ 'Ok' : AccountInfo, 'Err' : SetDefaultAccountError })],
880984
[],
881985
),
986+
'smtp_request' : IDL.Func([SmtpRequest], [SmtpResponse], []),
987+
'smtp_request_validate' : IDL.Func(
988+
[SmtpRequest],
989+
[SmtpResponse],
990+
['query'],
991+
),
882992
'stats' : IDL.Func([], [InternetIdentityStats], ['query']),
883993
'update' : IDL.Func([UserNumber, DeviceKey, DeviceData], [], []),
884994
'update_account' : IDL.Func(

0 commit comments

Comments
 (0)