zele 0.3.16 → 0.3.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/README.md +91 -36
  2. package/dist/api-utils.d.ts +4 -0
  3. package/dist/api-utils.js +6 -0
  4. package/dist/api-utils.js.map +1 -1
  5. package/dist/auth.d.ts +71 -9
  6. package/dist/auth.js +186 -10
  7. package/dist/auth.js.map +1 -1
  8. package/dist/commands/attachment.js +2 -0
  9. package/dist/commands/attachment.js.map +1 -1
  10. package/dist/commands/auth-cmd.js +104 -6
  11. package/dist/commands/auth-cmd.js.map +1 -1
  12. package/dist/commands/draft.js +7 -1
  13. package/dist/commands/draft.js.map +1 -1
  14. package/dist/commands/filter.js +7 -2
  15. package/dist/commands/filter.js.map +1 -1
  16. package/dist/commands/label.js +19 -9
  17. package/dist/commands/label.js.map +1 -1
  18. package/dist/commands/mail-actions.js.map +1 -1
  19. package/dist/commands/mail.js +49 -22
  20. package/dist/commands/mail.js.map +1 -1
  21. package/dist/commands/profile.js +25 -18
  22. package/dist/commands/profile.js.map +1 -1
  23. package/dist/db.js +24 -0
  24. package/dist/db.js.map +1 -1
  25. package/dist/generated/internal/class.js +2 -2
  26. package/dist/generated/internal/class.js.map +1 -1
  27. package/dist/generated/internal/prismaNamespace.d.ts +2 -0
  28. package/dist/generated/internal/prismaNamespace.js +2 -0
  29. package/dist/generated/internal/prismaNamespace.js.map +1 -1
  30. package/dist/generated/internal/prismaNamespaceBrowser.d.ts +2 -0
  31. package/dist/generated/internal/prismaNamespaceBrowser.js +2 -0
  32. package/dist/generated/internal/prismaNamespaceBrowser.js.map +1 -1
  33. package/dist/generated/models/Account.d.ts +97 -1
  34. package/dist/gmail-client.d.ts +14 -0
  35. package/dist/gmail-client.js +46 -0
  36. package/dist/gmail-client.js.map +1 -1
  37. package/dist/imap-smtp-client.d.ts +235 -0
  38. package/dist/imap-smtp-client.js +1225 -0
  39. package/dist/imap-smtp-client.js.map +1 -0
  40. package/dist/mail-tui.js.map +1 -1
  41. package/package.json +5 -2
  42. package/schema.prisma +7 -5
  43. package/skills/zele/SKILL.md +50 -21
  44. package/src/api-utils.ts +6 -0
  45. package/src/auth.ts +282 -14
  46. package/src/commands/attachment.ts +1 -0
  47. package/src/commands/auth-cmd.ts +112 -6
  48. package/src/commands/draft.ts +5 -1
  49. package/src/commands/filter.ts +9 -3
  50. package/src/commands/label.ts +22 -11
  51. package/src/commands/mail-actions.ts +2 -1
  52. package/src/commands/mail.ts +52 -22
  53. package/src/commands/profile.ts +27 -17
  54. package/src/db.ts +28 -0
  55. package/src/generated/internal/class.ts +2 -2
  56. package/src/generated/internal/prismaNamespace.ts +2 -0
  57. package/src/generated/internal/prismaNamespaceBrowser.ts +2 -0
  58. package/src/generated/models/Account.ts +97 -1
  59. package/src/gmail-client.test.ts +155 -2
  60. package/src/gmail-client.ts +65 -0
  61. package/src/imap-smtp-client.ts +1381 -0
  62. package/src/mail-tui.tsx +2 -1
  63. package/src/schema.sql +2 -0
@@ -27,6 +27,8 @@ export type AggregateAccount = {
27
27
  export type AccountMinAggregateOutputType = {
28
28
  email: string | null
29
29
  appId: string | null
30
+ accountType: string | null
31
+ capabilities: string | null
30
32
  accountStatus: $Enums.AccountStatus | null
31
33
  tokens: string | null
32
34
  createdAt: Date | null
@@ -36,6 +38,8 @@ export type AccountMinAggregateOutputType = {
36
38
  export type AccountMaxAggregateOutputType = {
37
39
  email: string | null
38
40
  appId: string | null
41
+ accountType: string | null
42
+ capabilities: string | null
39
43
  accountStatus: $Enums.AccountStatus | null
40
44
  tokens: string | null
41
45
  createdAt: Date | null
@@ -45,6 +49,8 @@ export type AccountMaxAggregateOutputType = {
45
49
  export type AccountCountAggregateOutputType = {
46
50
  email: number
47
51
  appId: number
52
+ accountType: number
53
+ capabilities: number
48
54
  accountStatus: number
49
55
  tokens: number
50
56
  createdAt: number
@@ -56,6 +62,8 @@ export type AccountCountAggregateOutputType = {
56
62
  export type AccountMinAggregateInputType = {
57
63
  email?: true
58
64
  appId?: true
65
+ accountType?: true
66
+ capabilities?: true
59
67
  accountStatus?: true
60
68
  tokens?: true
61
69
  createdAt?: true
@@ -65,6 +73,8 @@ export type AccountMinAggregateInputType = {
65
73
  export type AccountMaxAggregateInputType = {
66
74
  email?: true
67
75
  appId?: true
76
+ accountType?: true
77
+ capabilities?: true
68
78
  accountStatus?: true
69
79
  tokens?: true
70
80
  createdAt?: true
@@ -74,6 +84,8 @@ export type AccountMaxAggregateInputType = {
74
84
  export type AccountCountAggregateInputType = {
75
85
  email?: true
76
86
  appId?: true
87
+ accountType?: true
88
+ capabilities?: true
77
89
  accountStatus?: true
78
90
  tokens?: true
79
91
  createdAt?: true
@@ -156,6 +168,8 @@ export type AccountGroupByArgs<ExtArgs extends runtime.Types.Extensions.Internal
156
168
  export type AccountGroupByOutputType = {
157
169
  email: string
158
170
  appId: string
171
+ accountType: string
172
+ capabilities: string
159
173
  accountStatus: $Enums.AccountStatus
160
174
  tokens: string
161
175
  createdAt: Date
@@ -186,6 +200,8 @@ export type AccountWhereInput = {
186
200
  NOT?: Prisma.AccountWhereInput | Prisma.AccountWhereInput[]
187
201
  email?: Prisma.StringFilter<"Account"> | string
188
202
  appId?: Prisma.StringFilter<"Account"> | string
203
+ accountType?: Prisma.StringFilter<"Account"> | string
204
+ capabilities?: Prisma.StringFilter<"Account"> | string
189
205
  accountStatus?: Prisma.EnumAccountStatusFilter<"Account"> | $Enums.AccountStatus
190
206
  tokens?: Prisma.StringFilter<"Account"> | string
191
207
  createdAt?: Prisma.DateTimeFilter<"Account"> | Date | string
@@ -200,6 +216,8 @@ export type AccountWhereInput = {
200
216
  export type AccountOrderByWithRelationInput = {
201
217
  email?: Prisma.SortOrder
202
218
  appId?: Prisma.SortOrder
219
+ accountType?: Prisma.SortOrder
220
+ capabilities?: Prisma.SortOrder
203
221
  accountStatus?: Prisma.SortOrder
204
222
  tokens?: Prisma.SortOrder
205
223
  createdAt?: Prisma.SortOrder
@@ -218,6 +236,8 @@ export type AccountWhereUniqueInput = Prisma.AtLeast<{
218
236
  NOT?: Prisma.AccountWhereInput | Prisma.AccountWhereInput[]
219
237
  email?: Prisma.StringFilter<"Account"> | string
220
238
  appId?: Prisma.StringFilter<"Account"> | string
239
+ accountType?: Prisma.StringFilter<"Account"> | string
240
+ capabilities?: Prisma.StringFilter<"Account"> | string
221
241
  accountStatus?: Prisma.EnumAccountStatusFilter<"Account"> | $Enums.AccountStatus
222
242
  tokens?: Prisma.StringFilter<"Account"> | string
223
243
  createdAt?: Prisma.DateTimeFilter<"Account"> | Date | string
@@ -232,6 +252,8 @@ export type AccountWhereUniqueInput = Prisma.AtLeast<{
232
252
  export type AccountOrderByWithAggregationInput = {
233
253
  email?: Prisma.SortOrder
234
254
  appId?: Prisma.SortOrder
255
+ accountType?: Prisma.SortOrder
256
+ capabilities?: Prisma.SortOrder
235
257
  accountStatus?: Prisma.SortOrder
236
258
  tokens?: Prisma.SortOrder
237
259
  createdAt?: Prisma.SortOrder
@@ -247,6 +269,8 @@ export type AccountScalarWhereWithAggregatesInput = {
247
269
  NOT?: Prisma.AccountScalarWhereWithAggregatesInput | Prisma.AccountScalarWhereWithAggregatesInput[]
248
270
  email?: Prisma.StringWithAggregatesFilter<"Account"> | string
249
271
  appId?: Prisma.StringWithAggregatesFilter<"Account"> | string
272
+ accountType?: Prisma.StringWithAggregatesFilter<"Account"> | string
273
+ capabilities?: Prisma.StringWithAggregatesFilter<"Account"> | string
250
274
  accountStatus?: Prisma.EnumAccountStatusWithAggregatesFilter<"Account"> | $Enums.AccountStatus
251
275
  tokens?: Prisma.StringWithAggregatesFilter<"Account"> | string
252
276
  createdAt?: Prisma.DateTimeWithAggregatesFilter<"Account"> | Date | string
@@ -256,6 +280,8 @@ export type AccountScalarWhereWithAggregatesInput = {
256
280
  export type AccountCreateInput = {
257
281
  email: string
258
282
  appId: string
283
+ accountType?: string
284
+ capabilities?: string
259
285
  accountStatus: $Enums.AccountStatus
260
286
  tokens: string
261
287
  createdAt: Date | string
@@ -270,6 +296,8 @@ export type AccountCreateInput = {
270
296
  export type AccountUncheckedCreateInput = {
271
297
  email: string
272
298
  appId: string
299
+ accountType?: string
300
+ capabilities?: string
273
301
  accountStatus: $Enums.AccountStatus
274
302
  tokens: string
275
303
  createdAt: Date | string
@@ -284,6 +312,8 @@ export type AccountUncheckedCreateInput = {
284
312
  export type AccountUpdateInput = {
285
313
  email?: Prisma.StringFieldUpdateOperationsInput | string
286
314
  appId?: Prisma.StringFieldUpdateOperationsInput | string
315
+ accountType?: Prisma.StringFieldUpdateOperationsInput | string
316
+ capabilities?: Prisma.StringFieldUpdateOperationsInput | string
287
317
  accountStatus?: Prisma.EnumAccountStatusFieldUpdateOperationsInput | $Enums.AccountStatus
288
318
  tokens?: Prisma.StringFieldUpdateOperationsInput | string
289
319
  createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
@@ -298,6 +328,8 @@ export type AccountUpdateInput = {
298
328
  export type AccountUncheckedUpdateInput = {
299
329
  email?: Prisma.StringFieldUpdateOperationsInput | string
300
330
  appId?: Prisma.StringFieldUpdateOperationsInput | string
331
+ accountType?: Prisma.StringFieldUpdateOperationsInput | string
332
+ capabilities?: Prisma.StringFieldUpdateOperationsInput | string
301
333
  accountStatus?: Prisma.EnumAccountStatusFieldUpdateOperationsInput | $Enums.AccountStatus
302
334
  tokens?: Prisma.StringFieldUpdateOperationsInput | string
303
335
  createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
@@ -312,6 +344,8 @@ export type AccountUncheckedUpdateInput = {
312
344
  export type AccountCreateManyInput = {
313
345
  email: string
314
346
  appId: string
347
+ accountType?: string
348
+ capabilities?: string
315
349
  accountStatus: $Enums.AccountStatus
316
350
  tokens: string
317
351
  createdAt: Date | string
@@ -321,6 +355,8 @@ export type AccountCreateManyInput = {
321
355
  export type AccountUpdateManyMutationInput = {
322
356
  email?: Prisma.StringFieldUpdateOperationsInput | string
323
357
  appId?: Prisma.StringFieldUpdateOperationsInput | string
358
+ accountType?: Prisma.StringFieldUpdateOperationsInput | string
359
+ capabilities?: Prisma.StringFieldUpdateOperationsInput | string
324
360
  accountStatus?: Prisma.EnumAccountStatusFieldUpdateOperationsInput | $Enums.AccountStatus
325
361
  tokens?: Prisma.StringFieldUpdateOperationsInput | string
326
362
  createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
@@ -330,6 +366,8 @@ export type AccountUpdateManyMutationInput = {
330
366
  export type AccountUncheckedUpdateManyInput = {
331
367
  email?: Prisma.StringFieldUpdateOperationsInput | string
332
368
  appId?: Prisma.StringFieldUpdateOperationsInput | string
369
+ accountType?: Prisma.StringFieldUpdateOperationsInput | string
370
+ capabilities?: Prisma.StringFieldUpdateOperationsInput | string
333
371
  accountStatus?: Prisma.EnumAccountStatusFieldUpdateOperationsInput | $Enums.AccountStatus
334
372
  tokens?: Prisma.StringFieldUpdateOperationsInput | string
335
373
  createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
@@ -344,6 +382,8 @@ export type AccountEmailAppIdCompoundUniqueInput = {
344
382
  export type AccountCountOrderByAggregateInput = {
345
383
  email?: Prisma.SortOrder
346
384
  appId?: Prisma.SortOrder
385
+ accountType?: Prisma.SortOrder
386
+ capabilities?: Prisma.SortOrder
347
387
  accountStatus?: Prisma.SortOrder
348
388
  tokens?: Prisma.SortOrder
349
389
  createdAt?: Prisma.SortOrder
@@ -353,6 +393,8 @@ export type AccountCountOrderByAggregateInput = {
353
393
  export type AccountMaxOrderByAggregateInput = {
354
394
  email?: Prisma.SortOrder
355
395
  appId?: Prisma.SortOrder
396
+ accountType?: Prisma.SortOrder
397
+ capabilities?: Prisma.SortOrder
356
398
  accountStatus?: Prisma.SortOrder
357
399
  tokens?: Prisma.SortOrder
358
400
  createdAt?: Prisma.SortOrder
@@ -362,6 +404,8 @@ export type AccountMaxOrderByAggregateInput = {
362
404
  export type AccountMinOrderByAggregateInput = {
363
405
  email?: Prisma.SortOrder
364
406
  appId?: Prisma.SortOrder
407
+ accountType?: Prisma.SortOrder
408
+ capabilities?: Prisma.SortOrder
365
409
  accountStatus?: Prisma.SortOrder
366
410
  tokens?: Prisma.SortOrder
367
411
  createdAt?: Prisma.SortOrder
@@ -458,6 +502,8 @@ export type AccountUpdateOneRequiredWithoutSyncStatesNestedInput = {
458
502
  export type AccountCreateWithoutThreadsInput = {
459
503
  email: string
460
504
  appId: string
505
+ accountType?: string
506
+ capabilities?: string
461
507
  accountStatus: $Enums.AccountStatus
462
508
  tokens: string
463
509
  createdAt: Date | string
@@ -471,6 +517,8 @@ export type AccountCreateWithoutThreadsInput = {
471
517
  export type AccountUncheckedCreateWithoutThreadsInput = {
472
518
  email: string
473
519
  appId: string
520
+ accountType?: string
521
+ capabilities?: string
474
522
  accountStatus: $Enums.AccountStatus
475
523
  tokens: string
476
524
  createdAt: Date | string
@@ -500,6 +548,8 @@ export type AccountUpdateToOneWithWhereWithoutThreadsInput = {
500
548
  export type AccountUpdateWithoutThreadsInput = {
501
549
  email?: Prisma.StringFieldUpdateOperationsInput | string
502
550
  appId?: Prisma.StringFieldUpdateOperationsInput | string
551
+ accountType?: Prisma.StringFieldUpdateOperationsInput | string
552
+ capabilities?: Prisma.StringFieldUpdateOperationsInput | string
503
553
  accountStatus?: Prisma.EnumAccountStatusFieldUpdateOperationsInput | $Enums.AccountStatus
504
554
  tokens?: Prisma.StringFieldUpdateOperationsInput | string
505
555
  createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
@@ -513,6 +563,8 @@ export type AccountUpdateWithoutThreadsInput = {
513
563
  export type AccountUncheckedUpdateWithoutThreadsInput = {
514
564
  email?: Prisma.StringFieldUpdateOperationsInput | string
515
565
  appId?: Prisma.StringFieldUpdateOperationsInput | string
566
+ accountType?: Prisma.StringFieldUpdateOperationsInput | string
567
+ capabilities?: Prisma.StringFieldUpdateOperationsInput | string
516
568
  accountStatus?: Prisma.EnumAccountStatusFieldUpdateOperationsInput | $Enums.AccountStatus
517
569
  tokens?: Prisma.StringFieldUpdateOperationsInput | string
518
570
  createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
@@ -526,6 +578,8 @@ export type AccountUncheckedUpdateWithoutThreadsInput = {
526
578
  export type AccountCreateWithoutLabelsInput = {
527
579
  email: string
528
580
  appId: string
581
+ accountType?: string
582
+ capabilities?: string
529
583
  accountStatus: $Enums.AccountStatus
530
584
  tokens: string
531
585
  createdAt: Date | string
@@ -539,6 +593,8 @@ export type AccountCreateWithoutLabelsInput = {
539
593
  export type AccountUncheckedCreateWithoutLabelsInput = {
540
594
  email: string
541
595
  appId: string
596
+ accountType?: string
597
+ capabilities?: string
542
598
  accountStatus: $Enums.AccountStatus
543
599
  tokens: string
544
600
  createdAt: Date | string
@@ -568,6 +624,8 @@ export type AccountUpdateToOneWithWhereWithoutLabelsInput = {
568
624
  export type AccountUpdateWithoutLabelsInput = {
569
625
  email?: Prisma.StringFieldUpdateOperationsInput | string
570
626
  appId?: Prisma.StringFieldUpdateOperationsInput | string
627
+ accountType?: Prisma.StringFieldUpdateOperationsInput | string
628
+ capabilities?: Prisma.StringFieldUpdateOperationsInput | string
571
629
  accountStatus?: Prisma.EnumAccountStatusFieldUpdateOperationsInput | $Enums.AccountStatus
572
630
  tokens?: Prisma.StringFieldUpdateOperationsInput | string
573
631
  createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
@@ -581,6 +639,8 @@ export type AccountUpdateWithoutLabelsInput = {
581
639
  export type AccountUncheckedUpdateWithoutLabelsInput = {
582
640
  email?: Prisma.StringFieldUpdateOperationsInput | string
583
641
  appId?: Prisma.StringFieldUpdateOperationsInput | string
642
+ accountType?: Prisma.StringFieldUpdateOperationsInput | string
643
+ capabilities?: Prisma.StringFieldUpdateOperationsInput | string
584
644
  accountStatus?: Prisma.EnumAccountStatusFieldUpdateOperationsInput | $Enums.AccountStatus
585
645
  tokens?: Prisma.StringFieldUpdateOperationsInput | string
586
646
  createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
@@ -594,6 +654,8 @@ export type AccountUncheckedUpdateWithoutLabelsInput = {
594
654
  export type AccountCreateWithoutProfilesInput = {
595
655
  email: string
596
656
  appId: string
657
+ accountType?: string
658
+ capabilities?: string
597
659
  accountStatus: $Enums.AccountStatus
598
660
  tokens: string
599
661
  createdAt: Date | string
@@ -607,6 +669,8 @@ export type AccountCreateWithoutProfilesInput = {
607
669
  export type AccountUncheckedCreateWithoutProfilesInput = {
608
670
  email: string
609
671
  appId: string
672
+ accountType?: string
673
+ capabilities?: string
610
674
  accountStatus: $Enums.AccountStatus
611
675
  tokens: string
612
676
  createdAt: Date | string
@@ -636,6 +700,8 @@ export type AccountUpdateToOneWithWhereWithoutProfilesInput = {
636
700
  export type AccountUpdateWithoutProfilesInput = {
637
701
  email?: Prisma.StringFieldUpdateOperationsInput | string
638
702
  appId?: Prisma.StringFieldUpdateOperationsInput | string
703
+ accountType?: Prisma.StringFieldUpdateOperationsInput | string
704
+ capabilities?: Prisma.StringFieldUpdateOperationsInput | string
639
705
  accountStatus?: Prisma.EnumAccountStatusFieldUpdateOperationsInput | $Enums.AccountStatus
640
706
  tokens?: Prisma.StringFieldUpdateOperationsInput | string
641
707
  createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
@@ -649,6 +715,8 @@ export type AccountUpdateWithoutProfilesInput = {
649
715
  export type AccountUncheckedUpdateWithoutProfilesInput = {
650
716
  email?: Prisma.StringFieldUpdateOperationsInput | string
651
717
  appId?: Prisma.StringFieldUpdateOperationsInput | string
718
+ accountType?: Prisma.StringFieldUpdateOperationsInput | string
719
+ capabilities?: Prisma.StringFieldUpdateOperationsInput | string
652
720
  accountStatus?: Prisma.EnumAccountStatusFieldUpdateOperationsInput | $Enums.AccountStatus
653
721
  tokens?: Prisma.StringFieldUpdateOperationsInput | string
654
722
  createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
@@ -662,6 +730,8 @@ export type AccountUncheckedUpdateWithoutProfilesInput = {
662
730
  export type AccountCreateWithoutCalendarListsInput = {
663
731
  email: string
664
732
  appId: string
733
+ accountType?: string
734
+ capabilities?: string
665
735
  accountStatus: $Enums.AccountStatus
666
736
  tokens: string
667
737
  createdAt: Date | string
@@ -675,6 +745,8 @@ export type AccountCreateWithoutCalendarListsInput = {
675
745
  export type AccountUncheckedCreateWithoutCalendarListsInput = {
676
746
  email: string
677
747
  appId: string
748
+ accountType?: string
749
+ capabilities?: string
678
750
  accountStatus: $Enums.AccountStatus
679
751
  tokens: string
680
752
  createdAt: Date | string
@@ -704,6 +776,8 @@ export type AccountUpdateToOneWithWhereWithoutCalendarListsInput = {
704
776
  export type AccountUpdateWithoutCalendarListsInput = {
705
777
  email?: Prisma.StringFieldUpdateOperationsInput | string
706
778
  appId?: Prisma.StringFieldUpdateOperationsInput | string
779
+ accountType?: Prisma.StringFieldUpdateOperationsInput | string
780
+ capabilities?: Prisma.StringFieldUpdateOperationsInput | string
707
781
  accountStatus?: Prisma.EnumAccountStatusFieldUpdateOperationsInput | $Enums.AccountStatus
708
782
  tokens?: Prisma.StringFieldUpdateOperationsInput | string
709
783
  createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
@@ -717,6 +791,8 @@ export type AccountUpdateWithoutCalendarListsInput = {
717
791
  export type AccountUncheckedUpdateWithoutCalendarListsInput = {
718
792
  email?: Prisma.StringFieldUpdateOperationsInput | string
719
793
  appId?: Prisma.StringFieldUpdateOperationsInput | string
794
+ accountType?: Prisma.StringFieldUpdateOperationsInput | string
795
+ capabilities?: Prisma.StringFieldUpdateOperationsInput | string
720
796
  accountStatus?: Prisma.EnumAccountStatusFieldUpdateOperationsInput | $Enums.AccountStatus
721
797
  tokens?: Prisma.StringFieldUpdateOperationsInput | string
722
798
  createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
@@ -730,6 +806,8 @@ export type AccountUncheckedUpdateWithoutCalendarListsInput = {
730
806
  export type AccountCreateWithoutSyncStatesInput = {
731
807
  email: string
732
808
  appId: string
809
+ accountType?: string
810
+ capabilities?: string
733
811
  accountStatus: $Enums.AccountStatus
734
812
  tokens: string
735
813
  createdAt: Date | string
@@ -743,6 +821,8 @@ export type AccountCreateWithoutSyncStatesInput = {
743
821
  export type AccountUncheckedCreateWithoutSyncStatesInput = {
744
822
  email: string
745
823
  appId: string
824
+ accountType?: string
825
+ capabilities?: string
746
826
  accountStatus: $Enums.AccountStatus
747
827
  tokens: string
748
828
  createdAt: Date | string
@@ -772,6 +852,8 @@ export type AccountUpdateToOneWithWhereWithoutSyncStatesInput = {
772
852
  export type AccountUpdateWithoutSyncStatesInput = {
773
853
  email?: Prisma.StringFieldUpdateOperationsInput | string
774
854
  appId?: Prisma.StringFieldUpdateOperationsInput | string
855
+ accountType?: Prisma.StringFieldUpdateOperationsInput | string
856
+ capabilities?: Prisma.StringFieldUpdateOperationsInput | string
775
857
  accountStatus?: Prisma.EnumAccountStatusFieldUpdateOperationsInput | $Enums.AccountStatus
776
858
  tokens?: Prisma.StringFieldUpdateOperationsInput | string
777
859
  createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
@@ -785,6 +867,8 @@ export type AccountUpdateWithoutSyncStatesInput = {
785
867
  export type AccountUncheckedUpdateWithoutSyncStatesInput = {
786
868
  email?: Prisma.StringFieldUpdateOperationsInput | string
787
869
  appId?: Prisma.StringFieldUpdateOperationsInput | string
870
+ accountType?: Prisma.StringFieldUpdateOperationsInput | string
871
+ capabilities?: Prisma.StringFieldUpdateOperationsInput | string
788
872
  accountStatus?: Prisma.EnumAccountStatusFieldUpdateOperationsInput | $Enums.AccountStatus
789
873
  tokens?: Prisma.StringFieldUpdateOperationsInput | string
790
874
  createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
@@ -838,6 +922,8 @@ export type AccountCountOutputTypeCountSyncStatesArgs<ExtArgs extends runtime.Ty
838
922
  export type AccountSelect<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{
839
923
  email?: boolean
840
924
  appId?: boolean
925
+ accountType?: boolean
926
+ capabilities?: boolean
841
927
  accountStatus?: boolean
842
928
  tokens?: boolean
843
929
  createdAt?: boolean
@@ -853,6 +939,8 @@ export type AccountSelect<ExtArgs extends runtime.Types.Extensions.InternalArgs
853
939
  export type AccountSelectCreateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{
854
940
  email?: boolean
855
941
  appId?: boolean
942
+ accountType?: boolean
943
+ capabilities?: boolean
856
944
  accountStatus?: boolean
857
945
  tokens?: boolean
858
946
  createdAt?: boolean
@@ -862,6 +950,8 @@ export type AccountSelectCreateManyAndReturn<ExtArgs extends runtime.Types.Exten
862
950
  export type AccountSelectUpdateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{
863
951
  email?: boolean
864
952
  appId?: boolean
953
+ accountType?: boolean
954
+ capabilities?: boolean
865
955
  accountStatus?: boolean
866
956
  tokens?: boolean
867
957
  createdAt?: boolean
@@ -871,13 +961,15 @@ export type AccountSelectUpdateManyAndReturn<ExtArgs extends runtime.Types.Exten
871
961
  export type AccountSelectScalar = {
872
962
  email?: boolean
873
963
  appId?: boolean
964
+ accountType?: boolean
965
+ capabilities?: boolean
874
966
  accountStatus?: boolean
875
967
  tokens?: boolean
876
968
  createdAt?: boolean
877
969
  updatedAt?: boolean
878
970
  }
879
971
 
880
- export type AccountOmit<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetOmit<"email" | "appId" | "accountStatus" | "tokens" | "createdAt" | "updatedAt", ExtArgs["result"]["account"]>
972
+ export type AccountOmit<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetOmit<"email" | "appId" | "accountType" | "capabilities" | "accountStatus" | "tokens" | "createdAt" | "updatedAt", ExtArgs["result"]["account"]>
881
973
  export type AccountInclude<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
882
974
  threads?: boolean | Prisma.Account$threadsArgs<ExtArgs>
883
975
  labels?: boolean | Prisma.Account$labelsArgs<ExtArgs>
@@ -901,6 +993,8 @@ export type $AccountPayload<ExtArgs extends runtime.Types.Extensions.InternalArg
901
993
  scalars: runtime.Types.Extensions.GetPayloadResult<{
902
994
  email: string
903
995
  appId: string
996
+ accountType: string
997
+ capabilities: string
904
998
  accountStatus: $Enums.AccountStatus
905
999
  tokens: string
906
1000
  createdAt: Date
@@ -1335,6 +1429,8 @@ export interface Prisma__AccountClient<T, Null = never, ExtArgs extends runtime.
1335
1429
  export interface AccountFieldRefs {
1336
1430
  readonly email: Prisma.FieldRef<"Account", 'String'>
1337
1431
  readonly appId: Prisma.FieldRef<"Account", 'String'>
1432
+ readonly accountType: Prisma.FieldRef<"Account", 'String'>
1433
+ readonly capabilities: Prisma.FieldRef<"Account", 'String'>
1338
1434
  readonly accountStatus: Prisma.FieldRef<"Account", 'AccountStatus'>
1339
1435
  readonly tokens: Prisma.FieldRef<"Account", 'String'>
1340
1436
  readonly createdAt: Prisma.FieldRef<"Account", 'DateTime'>
@@ -1,9 +1,9 @@
1
1
  // Tests for GmailClient parsing behavior used by TUI previews.
2
2
  // Captures entity/encoding regressions in snippet fields from Gmail metadata responses.
3
3
 
4
- import { expect, test } from 'vitest'
4
+ import { expect, test, describe } from 'vitest'
5
5
  import { OAuth2Client } from 'google-auth-library'
6
- import { GmailClient } from './gmail-client.js'
6
+ import { GmailClient, parseAuthResults } from './gmail-client.js'
7
7
 
8
8
  // Create a real client instance for testing (no account context needed for parsing tests)
9
9
  const auth = new OAuth2Client()
@@ -62,3 +62,156 @@ test('thread list snippet strips zero-width and preheader garbage', () => {
62
62
  const parsed = client.parseThreadListItem(rawThread as any)
63
63
  expect(parsed.snippet).toBe('A host sent you a message')
64
64
  })
65
+
66
+ // ---------------------------------------------------------------------------
67
+ // parseAuthResults
68
+ // ---------------------------------------------------------------------------
69
+
70
+ describe('parseAuthResults', () => {
71
+ test('parses standard Gmail Authentication-Results header', () => {
72
+ const header = `mx.google.com;
73
+ dkim=pass header.i=@example.com header.s=selector1;
74
+ spf=pass (google.com: domain of user@example.com designates 1.2.3.4 as permitted sender) smtp.mailfrom=user@example.com;
75
+ dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=example.com`
76
+ const result = parseAuthResults(header)
77
+ expect(result).toMatchInlineSnapshot(`
78
+ {
79
+ "authentic": true,
80
+ "dkim": "pass",
81
+ "dmarc": "pass",
82
+ "raw": "mx.google.com;
83
+ dkim=pass header.i=@example.com header.s=selector1;
84
+ spf=pass (google.com: domain of user@example.com designates 1.2.3.4 as permitted sender) smtp.mailfrom=user@example.com;
85
+ dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=example.com",
86
+ "spf": "pass",
87
+ }
88
+ `)
89
+ })
90
+
91
+ test('detects failed authentication', () => {
92
+ const header = `mx.google.com;
93
+ dkim=fail (bad signature) header.i=@spoofed.com;
94
+ spf=softfail (google.com: domain transitioning) smtp.mailfrom=other.com;
95
+ dmarc=fail (p=REJECT) header.from=spoofed.com`
96
+ const result = parseAuthResults(header)
97
+ expect(result).toMatchInlineSnapshot(`
98
+ {
99
+ "authentic": false,
100
+ "dkim": "fail",
101
+ "dmarc": "fail",
102
+ "raw": "mx.google.com;
103
+ dkim=fail (bad signature) header.i=@spoofed.com;
104
+ spf=softfail (google.com: domain transitioning) smtp.mailfrom=other.com;
105
+ dmarc=fail (p=REJECT) header.from=spoofed.com",
106
+ "spf": "softfail",
107
+ }
108
+ `)
109
+ })
110
+
111
+ test('handles missing protocols gracefully', () => {
112
+ const header = `mx.google.com; spf=pass smtp.mailfrom=user@example.com`
113
+ const result = parseAuthResults(header)
114
+ expect(result).toMatchInlineSnapshot(`
115
+ {
116
+ "authentic": false,
117
+ "dkim": "none",
118
+ "dmarc": "none",
119
+ "raw": "mx.google.com; spf=pass smtp.mailfrom=user@example.com",
120
+ "spf": "pass",
121
+ }
122
+ `)
123
+ })
124
+
125
+ test('handles bestguesspass for DMARC', () => {
126
+ const header = `mx.google.com; dkim=pass header.i=@example.com; spf=pass; dmarc=bestguesspass header.from=example.com`
127
+ const result = parseAuthResults(header)
128
+ expect(result).toMatchInlineSnapshot(`
129
+ {
130
+ "authentic": false,
131
+ "dkim": "pass",
132
+ "dmarc": "bestguesspass",
133
+ "raw": "mx.google.com; dkim=pass header.i=@example.com; spf=pass; dmarc=bestguesspass header.from=example.com",
134
+ "spf": "pass",
135
+ }
136
+ `)
137
+ })
138
+
139
+ test('parseMessage includes auth for received messages', () => {
140
+ const rawMessage = {
141
+ id: 'msg_auth_1',
142
+ threadId: 'thread_auth_1',
143
+ snippet: 'Test',
144
+ payload: {
145
+ headers: [
146
+ { name: 'Subject', value: 'Auth test' },
147
+ { name: 'From', value: 'sender@example.com' },
148
+ { name: 'To', value: 'me@example.com' },
149
+ { name: 'Date', value: 'Wed, 25 Mar 2026 10:00:00 +0000' },
150
+ { name: 'Authentication-Results', value: 'mx.google.com; dkim=pass header.i=@example.com; spf=pass; dmarc=pass (p=REJECT) header.from=example.com' },
151
+ ],
152
+ mimeType: 'text/plain',
153
+ body: { data: Buffer.from('hello').toString('base64url') },
154
+ },
155
+ labelIds: ['INBOX'],
156
+ }
157
+ const parsed = client.parseMessage(rawMessage as any)
158
+ expect(parsed.auth).toMatchInlineSnapshot(`
159
+ {
160
+ "authentic": true,
161
+ "dkim": "pass",
162
+ "dmarc": "pass",
163
+ "raw": "mx.google.com; dkim=pass header.i=@example.com; spf=pass; dmarc=pass (p=REJECT) header.from=example.com",
164
+ "spf": "pass",
165
+ }
166
+ `)
167
+ })
168
+
169
+ test('parseMessage prefers Gmail trusted header over upstream headers', () => {
170
+ const rawMessage = {
171
+ id: 'msg_multi_auth',
172
+ threadId: 'thread_multi_auth',
173
+ snippet: 'Multi-header',
174
+ payload: {
175
+ headers: [
176
+ { name: 'Subject', value: 'Forwarded' },
177
+ { name: 'From', value: 'sender@example.com' },
178
+ { name: 'To', value: 'me@example.com' },
179
+ { name: 'Date', value: 'Wed, 25 Mar 2026 10:00:00 +0000' },
180
+ // Upstream relay header (untrusted, appears first)
181
+ { name: 'Authentication-Results', value: 'relay.untrusted.com; dkim=fail; spf=fail; dmarc=fail' },
182
+ // Gmail's trusted header (should be preferred)
183
+ { name: 'Authentication-Results', value: 'mx.google.com; dkim=pass header.i=@example.com; spf=pass; dmarc=pass (p=REJECT)' },
184
+ ],
185
+ mimeType: 'text/plain',
186
+ body: { data: Buffer.from('hello').toString('base64url') },
187
+ },
188
+ labelIds: ['INBOX'],
189
+ }
190
+ const parsed = client.parseMessage(rawMessage as any)
191
+ expect(parsed.auth?.authentic).toBe(true)
192
+ expect(parsed.auth?.spf).toBe('pass')
193
+ expect(parsed.auth?.dkim).toBe('pass')
194
+ expect(parsed.auth?.dmarc).toBe('pass')
195
+ })
196
+
197
+ test('parseMessage returns null auth for sent messages', () => {
198
+ const rawMessage = {
199
+ id: 'msg_sent_1',
200
+ threadId: 'thread_sent_1',
201
+ snippet: 'Sent',
202
+ payload: {
203
+ headers: [
204
+ { name: 'Subject', value: 'Outgoing' },
205
+ { name: 'From', value: 'me@example.com' },
206
+ { name: 'To', value: 'other@example.com' },
207
+ { name: 'Date', value: 'Wed, 25 Mar 2026 10:00:00 +0000' },
208
+ ],
209
+ mimeType: 'text/plain',
210
+ body: { data: Buffer.from('hello').toString('base64url') },
211
+ },
212
+ labelIds: ['SENT'],
213
+ }
214
+ const parsed = client.parseMessage(rawMessage as any)
215
+ expect(parsed.auth).toBeNull()
216
+ })
217
+ })
@@ -22,6 +22,18 @@ import type { AccountId } from './auth.js'
22
22
  // Types
23
23
  // ---------------------------------------------------------------------------
24
24
 
25
+ export type AuthVerdict = 'pass' | 'fail' | 'softfail' | 'neutral' | 'none' | 'temperror' | 'permerror' | 'bestguesspass'
26
+
27
+ export interface AuthResult {
28
+ spf: AuthVerdict
29
+ dkim: AuthVerdict
30
+ dmarc: AuthVerdict
31
+ /** true when all three are 'pass' — the email is fully authenticated */
32
+ authentic: boolean
33
+ /** raw Authentication-Results header value */
34
+ raw: string
35
+ }
36
+
25
37
  export interface Sender {
26
38
  name?: string
27
39
  email: string
@@ -50,6 +62,8 @@ export interface ParsedMessage {
50
62
  mimeType: string // 'text/plain' or 'text/html'
51
63
  textBody: string | null // decoded text/plain body when available (for reply parsing)
52
64
  attachments: AttachmentMeta[]
65
+ /** SPF/DKIM/DMARC authentication results from Gmail. null for sent/draft messages. */
66
+ auth: AuthResult | null
53
67
  }
54
68
 
55
69
  export interface AttachmentMeta {
@@ -1282,6 +1296,20 @@ export class GmailClient {
1282
1296
 
1283
1297
  const { body, mimeType, textBody } = this.extractBody(message.payload ?? {})
1284
1298
 
1299
+ // Authentication-Results: multiple MTAs can add this header. Prefer the one
1300
+ // stamped by Gmail's trusted authserv-id (mx.google.com) to avoid trusting
1301
+ // headers injected by upstream/untrusted relays.
1302
+ const authHeaders = headers
1303
+ .filter((h) => h.name?.toLowerCase() === 'authentication-results')
1304
+ .map((h) => h.value ?? '')
1305
+ .filter((v) => v.length > 0)
1306
+ const trustedAuthHeader =
1307
+ authHeaders.find((v) => v.trim().toLowerCase().startsWith('mx.google.com'))
1308
+ ?? authHeaders[0]
1309
+ ?? null
1310
+ const isSentOrDraft = labelIds.includes('SENT') || labelIds.includes('DRAFT')
1311
+ const auth = trustedAuthHeader && !isSentOrDraft ? parseAuthResults(trustedAuthHeader) : null
1312
+
1285
1313
  return {
1286
1314
  id: message.id ?? '',
1287
1315
  threadId: message.threadId ?? '',
@@ -1308,6 +1336,7 @@ export class GmailClient {
1308
1336
  mimeType,
1309
1337
  textBody,
1310
1338
  attachments: this.extractAttachmentMeta(message.payload?.parts ?? []),
1339
+ auth,
1311
1340
  }
1312
1341
  }
1313
1342
 
@@ -2015,6 +2044,42 @@ export class GmailClient {
2015
2044
  }
2016
2045
  }
2017
2046
 
2047
+ // ---------------------------------------------------------------------------
2048
+ // Email authentication: parse the Authentication-Results header
2049
+ // ---------------------------------------------------------------------------
2050
+ // Gmail adds an Authentication-Results header to every received message with
2051
+ // SPF, DKIM, and DMARC verdicts. Format is semi-structured:
2052
+ // Authentication-Results: mx.google.com;
2053
+ // dkim=pass header.i=@example.com header.s=sel1;
2054
+ // spf=pass (...) smtp.mailfrom=user@example.com;
2055
+ // dmarc=pass (p=REJECT) header.from=example.com
2056
+ // We extract the verdict keyword after each protocol name.
2057
+ // ---------------------------------------------------------------------------
2058
+
2059
+ const AUTH_VERDICTS = new Set(['pass', 'fail', 'softfail', 'neutral', 'none', 'temperror', 'permerror', 'bestguesspass'])
2060
+
2061
+ /** Parse a Gmail Authentication-Results header into structured verdicts. */
2062
+ export function parseAuthResults(header: string): AuthResult {
2063
+ const lower = header.toLowerCase()
2064
+ const extract = (protocol: string): AuthVerdict => {
2065
+ // Match "protocol=verdict" — verdict is a word that stops at whitespace, semicolons, or parens
2066
+ const re = new RegExp(`\\b${protocol}\\s*=\\s*([a-z]+)`)
2067
+ const match = re.exec(lower)
2068
+ const verdict = match?.[1] ?? 'none'
2069
+ return AUTH_VERDICTS.has(verdict) ? verdict as AuthVerdict : 'none'
2070
+ }
2071
+ const spf = extract('spf')
2072
+ const dkim = extract('dkim')
2073
+ const dmarc = extract('dmarc')
2074
+ return {
2075
+ spf,
2076
+ dkim,
2077
+ dmarc,
2078
+ authentic: spf === 'pass' && dkim === 'pass' && dmarc === 'pass',
2079
+ raw: header,
2080
+ }
2081
+ }
2082
+
2018
2083
  // ---------------------------------------------------------------------------
2019
2084
  // Watch: folder label mapping
2020
2085
  // ---------------------------------------------------------------------------