1package daemonrpc
2
3import "encoding/json"
4
5// Request from client to daemon. Has an ID for matching responses.
6type Request struct {
7 ID uint64 `json:"id"`
8 Method string `json:"method"`
9 Params json.RawMessage `json:"params,omitempty"`
10}
11
12// Response from daemon to client. Matched to request by ID.
13type Response struct {
14 ID uint64 `json:"id"`
15 Result json.RawMessage `json:"result,omitempty"`
16 Error *Error `json:"error,omitempty"`
17}
18
19// Event pushed from daemon to subscribed clients. No ID field.
20type Event struct {
21 Type string `json:"type"`
22 Data json.RawMessage `json:"data,omitempty"`
23}
24
25// Error returned in a Response.
26type Error struct {
27 Code int `json:"code"`
28 Message string `json:"message"`
29}
30
31func (e *Error) Error() string { return e.Message }
32
33// Message is a union type for wire decoding. Exactly one of the
34// fields will be populated based on the presence of "id" and "type".
35type Message struct {
36 Request *Request
37 Response *Response
38 Event *Event
39}
40
41// Discriminate: if "type" present → Event, if "method" present → Request, else → Response.
42func DecodeMessage(raw json.RawMessage) (Message, error) {
43 var probe struct {
44 Type string `json:"type"`
45 Method string `json:"method"`
46 ID *uint64 `json:"id"`
47 }
48 if err := json.Unmarshal(raw, &probe); err != nil {
49 return Message{}, err
50 }
51
52 var m Message
53 if probe.Type != "" {
54 var ev Event
55 if err := json.Unmarshal(raw, &ev); err != nil {
56 return m, err
57 }
58 m.Event = &ev
59 } else if probe.Method != "" {
60 var req Request
61 if err := json.Unmarshal(raw, &req); err != nil {
62 return m, err
63 }
64 m.Request = &req
65 } else {
66 var resp Response
67 if err := json.Unmarshal(raw, &resp); err != nil {
68 return m, err
69 }
70 m.Response = &resp
71 }
72 return m, nil
73}
74
75// Standard error codes.
76const (
77 ErrCodeParse = -32700
78 ErrCodeInvalidReq = -32600
79 ErrCodeNotFound = -32601
80 ErrCodeInternal = -32603
81)
82
83// RPC method names.
84const (
85 MethodPing = "Ping"
86 MethodGetStatus = "GetStatus"
87 MethodGetAccounts = "GetAccounts"
88 MethodReloadConfig = "ReloadConfig"
89 MethodFetchEmails = "FetchEmails"
90 MethodFetchEmailBody = "FetchEmailBody"
91 MethodSendEmail = "SendEmail"
92 MethodDeleteEmails = "DeleteEmails"
93 MethodArchiveEmails = "ArchiveEmails"
94 MethodMoveEmails = "MoveEmails"
95 MethodMarkRead = "MarkRead"
96 MethodFetchFolders = "FetchFolders"
97 MethodRefreshFolder = "RefreshFolder"
98 MethodSubscribe = "Subscribe"
99 MethodUnsubscribe = "Unsubscribe"
100 MethodSendRSVP = "SendRSVP"
101 MethodGetCachedEmails = "GetCachedEmails"
102 MethodGetCachedBody = "GetCachedBody"
103 MethodExportContacts = "ExportContacts"
104)
105
106// Event type names.
107const (
108 EventNewMail = "NewMail"
109 EventSyncStarted = "SyncStarted"
110 EventSyncComplete = "SyncComplete"
111 EventSyncError = "SyncError"
112 EventEmailsUpdated = "EmailsUpdated"
113 EventConfigReloaded = "ConfigReloaded"
114)
115
116// Param/result types for RPC methods.
117
118type PingResult struct {
119 Pong bool `json:"pong"`
120}
121
122type StatusResult struct {
123 Running bool `json:"running"`
124 Uptime int64 `json:"uptime_seconds"`
125 Accounts []string `json:"accounts"`
126 PID int `json:"pid"`
127}
128
129type AccountInfo struct {
130 ID string `json:"id"`
131 Name string `json:"name"`
132 Email string `json:"email"`
133 Protocol string `json:"protocol"`
134}
135
136type FetchEmailsParams struct {
137 AccountID string `json:"account_id"`
138 Folder string `json:"folder"`
139 Limit uint32 `json:"limit"`
140 Offset uint32 `json:"offset"`
141}
142
143type FetchEmailBodyParams struct {
144 AccountID string `json:"account_id"`
145 Folder string `json:"folder"`
146 UID uint32 `json:"uid"`
147}
148
149type FetchEmailBodyResult struct {
150 Body string `json:"body"`
151 BodyMIMEType string `json:"body_mime_type,omitempty"`
152 Attachments []AttachmentInfo `json:"attachments"`
153}
154
155type AttachmentInfo struct {
156 Filename string `json:"filename"`
157 PartID string `json:"part_id"`
158 Encoding string `json:"encoding"`
159 MIMEType string `json:"mime_type"`
160 IsCalendarInvite bool `json:"is_calendar_invite,omitempty"`
161 CalendarData []byte `json:"calendar_data,omitempty"`
162}
163
164type SendEmailParams struct {
165 AccountID string `json:"account_id"`
166 To []string `json:"to"`
167 Cc []string `json:"cc,omitempty"`
168 Bcc []string `json:"bcc,omitempty"`
169 Subject string `json:"subject"`
170 Body string `json:"body"`
171 HTMLBody string `json:"html_body,omitempty"`
172 Attachments map[string][]byte `json:"attachments,omitempty"`
173 InReplyTo string `json:"in_reply_to,omitempty"`
174 References []string `json:"references,omitempty"`
175 SignSMIME bool `json:"sign_smime,omitempty"`
176 EncryptSMIME bool `json:"encrypt_smime,omitempty"`
177 SignPGP bool `json:"sign_pgp,omitempty"`
178 EncryptPGP bool `json:"encrypt_pgp,omitempty"`
179}
180
181type DeleteEmailsParams struct {
182 AccountID string `json:"account_id"`
183 Folder string `json:"folder"`
184 UIDs []uint32 `json:"uids"`
185}
186
187type ArchiveEmailsParams struct {
188 AccountID string `json:"account_id"`
189 Folder string `json:"folder"`
190 UIDs []uint32 `json:"uids"`
191}
192
193type MoveEmailsParams struct {
194 AccountID string `json:"account_id"`
195 UIDs []uint32 `json:"uids"`
196 SourceFolder string `json:"source_folder"`
197 DestFolder string `json:"dest_folder"`
198}
199
200type MarkReadParams struct {
201 AccountID string `json:"account_id"`
202 Folder string `json:"folder"`
203 UIDs []uint32 `json:"uids"`
204 Read bool `json:"read"`
205}
206
207type FetchFoldersParams struct {
208 AccountID string `json:"account_id"`
209}
210
211type RefreshFolderParams struct {
212 AccountID string `json:"account_id"`
213 Folder string `json:"folder"`
214}
215
216type SubscribeParams struct {
217 AccountID string `json:"account_id"`
218 Folder string `json:"folder"`
219}
220
221type UnsubscribeParams struct {
222 AccountID string `json:"account_id"`
223 Folder string `json:"folder"`
224}
225
226type SendRSVPParams struct {
227 AccountID string `json:"account_id"`
228 OriginalICS []byte `json:"original_ics"`
229 Response string `json:"response"`
230 InReplyTo string `json:"in_reply_to,omitempty"`
231 References []string `json:"references,omitempty"`
232}
233
234type GetCachedEmailsParams struct {
235 Folder string `json:"folder"`
236}
237
238type GetCachedBodyParams struct {
239 Folder string `json:"folder"`
240 UID uint32 `json:"uid"`
241 AccountID string `json:"account_id"`
242}
243
244type ExportContactsParams struct {
245 Format string `json:"format"` // "json" or "csv"
246}
247
248// Event data types.
249
250type NewMailEvent struct {
251 AccountID string `json:"account_id"`
252 Folder string `json:"folder"`
253}
254
255type SyncStartedEvent struct {
256 AccountID string `json:"account_id"`
257 Folder string `json:"folder"`
258}
259
260type SyncCompleteEvent struct {
261 AccountID string `json:"account_id"`
262 Folder string `json:"folder"`
263 EmailCount int `json:"email_count"`
264}
265
266type SyncErrorEvent struct {
267 AccountID string `json:"account_id"`
268 Folder string `json:"folder"`
269 Error string `json:"error"`
270}