1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
#ifndef HYBBX_MAIL_H
#define HYBBX_MAIL_H
#include "hybbx/config.h"
#include "hybbx/storage.h"
#include "hybbx/types.h"
#include <time.h>
#ifdef __cplusplus
extern "C" {
#endif
struct hybbx_service;
struct hybbx_session;
/** Maximum stored messages per user inbox. */
#define HYBBX_MAIL_MAX_MESSAGES 50u
/** Subject line limit (80-column profile). */
#define HYBBX_MAIL_SUBJECT_MAX 72u
/** Total message body size (all lines). */
#define HYBBX_MAIL_BODY_MAX 2048u
/** Default days before recycled mail is permanently removed. */
#define HYBBX_MAIL_DEFAULT_RECYCLE_DAYS 10u
typedef struct hybbx_mail_config {
int enabled;
unsigned max_messages;
unsigned subject_max;
unsigned body_max;
unsigned recycle_days;
/** Root mail directory (typically <storage>/mail). */
char root[512];
} hybbx_mail_config_t;
typedef struct hybbx_mail_entry {
uint64_t id;
char from[64];
char subject[HYBBX_MAIL_SUBJECT_MAX];
time_t received_at;
int read;
} hybbx_mail_entry_t;
void hybbx_mail_config_defaults(hybbx_mail_config_t *mail);
/** Load `[mail]` and set @p mail->root under @p storage_path. */
void hybbx_mail_config_apply(hybbx_mail_config_t *mail,
const hybbx_config_t *config,
const char *storage_path);
const hybbx_mail_config_t *hybbx_service_get_mail(const struct hybbx_service *service);
/** List inbox on @p session (registered users only). */
void hybbx_mail_list_inbox(struct hybbx_service *service,
struct hybbx_session *session);
/**
* List inbox rows @p from..@p to (1-based, newest first).
* @p to = 0 means through the last message.
*/
void hybbx_mail_list_inbox_range(struct hybbx_service *service,
struct hybbx_session *session,
unsigned from, unsigned to);
/**
* After login: if mail arrived since @p since_login, announce the count.
* No output when mail is disabled, the user is a guest, or the count is zero.
* @p since_login 0 means first login (all inbox messages count as new).
*/
void hybbx_mail_announce_since_last_login(struct hybbx_service *service,
struct hybbx_session *session,
time_t since_login);
/**
* Parse @p spec as @c from-to (e.g. @c 1-15 , @c 5-20 ) or a single index.
* Returns 0 on invalid input.
*/
int hybbx_mail_parse_list_range(const char *spec,
unsigned *from, unsigned *to);
/**
* Read message by 1-based list index (newest first).
* Marks the message as read.
*/
hybbx_result_t hybbx_mail_read(struct hybbx_service *service,
struct hybbx_session *session,
unsigned list_index);
/** Move inbox message(s) to recycle (1-based index or range). */
hybbx_result_t hybbx_mail_delete(struct hybbx_service *service,
struct hybbx_session *session,
unsigned list_index);
hybbx_result_t hybbx_mail_delete_range(struct hybbx_service *service,
struct hybbx_session *session,
unsigned from, unsigned to);
/** Permanently remove all messages in the user's recycle bin. */
hybbx_result_t hybbx_mail_recycle_empty(struct hybbx_service *service,
struct hybbx_session *session);
/**
* Deliver a message from @p from_user to @p to_user.
* @p to_user must exist and be an active registered account.
*/
hybbx_result_t hybbx_mail_deliver(struct hybbx_service *service,
const char *from_user,
const char *to_user,
const char *subject,
const char *body);
/**
* Mail active Sysop and Admin when a guest self-registers.
* Body lists every field from `/register` plus assigned account metadata.
* No-op when mail is disabled. Individual delivery failures are ignored.
*/
hybbx_result_t hybbx_mail_notify_staff_registration(
struct hybbx_service *service,
const hybbx_user_registration_t *reg,
const hybbx_user_record_t *user);
#ifdef __cplusplus
}
#endif
#endif /* HYBBX_MAIL_H */
|