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 switch {
54 case probe.Type != "":
55 var ev Event
56 if err := json.Unmarshal(raw, &ev); err != nil {
57 return m, err
58 }
59 m.Event = &ev
60 case probe.Method != "":
61 var req Request
62 if err := json.Unmarshal(raw, &req); err != nil {
63 return m, err
64 }
65 m.Request = &req
66 default:
67 var resp Response
68 if err := json.Unmarshal(raw, &resp); err != nil {
69 return m, err
70 }
71 m.Response = &resp
72 }
73 return m, nil
74}
75
76// Standard error codes.
77const (
78 ErrCodeParse = -32700
79 ErrCodeInvalidReq = -32600
80 ErrCodeNotFound = -32601
81 ErrCodeInternal = -32603
82)
83
84// RPC method names.
85const (
86 MethodPing = "Ping"
87 MethodGetStatus = "GetStatus"
88 MethodGetAccounts = "GetAccounts"
89 MethodReloadConfig = "ReloadConfig"
90 MethodFetchEmails = "FetchEmails"
91 MethodFetchEmailBody = "FetchEmailBody"
92 MethodSendEmail = "SendEmail"
93 MethodDeleteEmails = "DeleteEmails"
94 MethodArchiveEmails = "ArchiveEmails"
95 MethodMoveEmails = "MoveEmails"
96 MethodMarkRead = "MarkRead"
97 MethodFetchFolders = "FetchFolders"
98 MethodRefreshFolder = "RefreshFolder"
99 MethodSubscribe = "Subscribe"
100 MethodUnsubscribe = "Unsubscribe"
101 MethodSendRSVP = "SendRSVP"
102 MethodGetCachedEmails = "GetCachedEmails"
103 MethodGetCachedBody = "GetCachedBody"
104 MethodExportContacts = "ExportContacts"
105)
106
107// Event type names.
108const (
109 EventNewMail = "NewMail"
110 EventSyncStarted = "SyncStarted"
111 EventSyncComplete = "SyncComplete"
112 EventSyncError = "SyncError"
113 EventEmailsUpdated = "EmailsUpdated"
114 EventConfigReloaded = "ConfigReloaded"
115)
116
117// Param/result types for RPC methods.
118
119type PingResult struct {
120 Pong bool `json:"pong"`
121}
122
123type StatusResult struct {
124 Running bool `json:"running"`
125 Uptime int64 `json:"uptime_seconds"`
126 Accounts []string `json:"accounts"`
127 PID int `json:"pid"`
128}
129
130type AccountInfo struct {
131 ID string `json:"id"`
132 Name string `json:"name"`
133 Email string `json:"email"`
134 Protocol string `json:"protocol"`
135}
136
137type FetchEmailsParams struct {
138 AccountID string `json:"account_id"`
139 Folder string `json:"folder"`
140 Limit uint32 `json:"limit"`
141 Offset uint32 `json:"offset"`
142}
143
144type FetchEmailBodyParams struct {
145 AccountID string `json:"account_id"`
146 Folder string `json:"folder"`
147 UID uint32 `json:"uid"`
148}
149
150type FetchEmailBodyResult struct {
151 Body string `json:"body"`
152 BodyMIMEType string `json:"body_mime_type,omitempty"`
153 Attachments []AttachmentInfo `json:"attachments"`
154}
155
156type AttachmentInfo struct {
157 Filename string `json:"filename"`
158 PartID string `json:"part_id"`
159 Encoding string `json:"encoding"`
160 MIMEType string `json:"mime_type"`
161 IsCalendarInvite bool `json:"is_calendar_invite,omitempty"`
162 CalendarData []byte `json:"calendar_data,omitempty"`
163}
164
165type SendEmailParams struct {
166 AccountID string `json:"account_id"`
167 To []string `json:"to"`
168 Cc []string `json:"cc,omitempty"`
169 Bcc []string `json:"bcc,omitempty"`
170 Subject string `json:"subject"`
171 Body string `json:"body"`
172 HTMLBody string `json:"html_body,omitempty"`
173 Attachments map[string][]byte `json:"attachments,omitempty"`
174 InReplyTo string `json:"in_reply_to,omitempty"`
175 References []string `json:"references,omitempty"`
176 SignSMIME bool `json:"sign_smime,omitempty"`
177 EncryptSMIME bool `json:"encrypt_smime,omitempty"`
178 SignPGP bool `json:"sign_pgp,omitempty"`
179 EncryptPGP bool `json:"encrypt_pgp,omitempty"`
180}
181
182type DeleteEmailsParams struct {
183 AccountID string `json:"account_id"`
184 Folder string `json:"folder"`
185 UIDs []uint32 `json:"uids"`
186}
187
188type ArchiveEmailsParams struct {
189 AccountID string `json:"account_id"`
190 Folder string `json:"folder"`
191 UIDs []uint32 `json:"uids"`
192}
193
194type MoveEmailsParams struct {
195 AccountID string `json:"account_id"`
196 UIDs []uint32 `json:"uids"`
197 SourceFolder string `json:"source_folder"`
198 DestFolder string `json:"dest_folder"`
199}
200
201type MarkReadParams struct {
202 AccountID string `json:"account_id"`
203 Folder string `json:"folder"`
204 UIDs []uint32 `json:"uids"`
205 Read bool `json:"read"`
206}
207
208type FetchFoldersParams struct {
209 AccountID string `json:"account_id"`
210}
211
212type RefreshFolderParams struct {
213 AccountID string `json:"account_id"`
214 Folder string `json:"folder"`
215}
216
217type SubscribeParams struct {
218 AccountID string `json:"account_id"`
219 Folder string `json:"folder"`
220}
221
222type UnsubscribeParams struct {
223 AccountID string `json:"account_id"`
224 Folder string `json:"folder"`
225}
226
227type SendRSVPParams struct {
228 AccountID string `json:"account_id"`
229 OriginalICS []byte `json:"original_ics"`
230 Response string `json:"response"`
231 InReplyTo string `json:"in_reply_to,omitempty"`
232 References []string `json:"references,omitempty"`
233}
234
235type GetCachedEmailsParams struct {
236 Folder string `json:"folder"`
237}
238
239type GetCachedBodyParams struct {
240 Folder string `json:"folder"`
241 UID uint32 `json:"uid"`
242 AccountID string `json:"account_id"`
243}
244
245type ExportContactsParams struct {
246 Format string `json:"format"` // "json" or "csv"
247}
248
249// Event data types.
250
251type NewMailEvent struct {
252 AccountID string `json:"account_id"`
253 Folder string `json:"folder"`
254}
255
256type SyncStartedEvent struct {
257 AccountID string `json:"account_id"`
258 Folder string `json:"folder"`
259}
260
261type SyncCompleteEvent struct {
262 AccountID string `json:"account_id"`
263 Folder string `json:"folder"`
264 EmailCount int `json:"email_count"`
265}
266
267type SyncErrorEvent struct {
268 AccountID string `json:"account_id"`
269 Folder string `json:"folder"`
270 Error string `json:"error"`
271}