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 Attachments []AttachmentInfo `json:"attachments"`
152}
153
154type AttachmentInfo struct {
155 Filename string `json:"filename"`
156 PartID string `json:"part_id"`
157 Encoding string `json:"encoding"`
158 MIMEType string `json:"mime_type"`
159 IsCalendarInvite bool `json:"is_calendar_invite,omitempty"`
160 CalendarData []byte `json:"calendar_data,omitempty"`
161}
162
163type SendEmailParams struct {
164 AccountID string `json:"account_id"`
165 To []string `json:"to"`
166 Cc []string `json:"cc,omitempty"`
167 Bcc []string `json:"bcc,omitempty"`
168 Subject string `json:"subject"`
169 Body string `json:"body"`
170 HTMLBody string `json:"html_body,omitempty"`
171 Attachments map[string][]byte `json:"attachments,omitempty"`
172 InReplyTo string `json:"in_reply_to,omitempty"`
173 References []string `json:"references,omitempty"`
174 SignSMIME bool `json:"sign_smime,omitempty"`
175 EncryptSMIME bool `json:"encrypt_smime,omitempty"`
176 SignPGP bool `json:"sign_pgp,omitempty"`
177 EncryptPGP bool `json:"encrypt_pgp,omitempty"`
178}
179
180type DeleteEmailsParams struct {
181 AccountID string `json:"account_id"`
182 Folder string `json:"folder"`
183 UIDs []uint32 `json:"uids"`
184}
185
186type ArchiveEmailsParams struct {
187 AccountID string `json:"account_id"`
188 Folder string `json:"folder"`
189 UIDs []uint32 `json:"uids"`
190}
191
192type MoveEmailsParams struct {
193 AccountID string `json:"account_id"`
194 UIDs []uint32 `json:"uids"`
195 SourceFolder string `json:"source_folder"`
196 DestFolder string `json:"dest_folder"`
197}
198
199type MarkReadParams struct {
200 AccountID string `json:"account_id"`
201 Folder string `json:"folder"`
202 UIDs []uint32 `json:"uids"`
203 Read bool `json:"read"`
204}
205
206type FetchFoldersParams struct {
207 AccountID string `json:"account_id"`
208}
209
210type RefreshFolderParams struct {
211 AccountID string `json:"account_id"`
212 Folder string `json:"folder"`
213}
214
215type SubscribeParams struct {
216 AccountID string `json:"account_id"`
217 Folder string `json:"folder"`
218}
219
220type UnsubscribeParams struct {
221 AccountID string `json:"account_id"`
222 Folder string `json:"folder"`
223}
224
225type SendRSVPParams struct {
226 AccountID string `json:"account_id"`
227 OriginalICS []byte `json:"original_ics"`
228 Response string `json:"response"`
229 InReplyTo string `json:"in_reply_to,omitempty"`
230 References []string `json:"references,omitempty"`
231}
232
233type GetCachedEmailsParams struct {
234 Folder string `json:"folder"`
235}
236
237type GetCachedBodyParams struct {
238 Folder string `json:"folder"`
239 UID uint32 `json:"uid"`
240 AccountID string `json:"account_id"`
241}
242
243type ExportContactsParams struct {
244 Format string `json:"format"` // "json" or "csv"
245}
246
247// Event data types.
248
249type NewMailEvent struct {
250 AccountID string `json:"account_id"`
251 Folder string `json:"folder"`
252}
253
254type SyncStartedEvent struct {
255 AccountID string `json:"account_id"`
256 Folder string `json:"folder"`
257}
258
259type SyncCompleteEvent struct {
260 AccountID string `json:"account_id"`
261 Folder string `json:"folder"`
262 EmailCount int `json:"email_count"`
263}
264
265type SyncErrorEvent struct {
266 AccountID string `json:"account_id"`
267 Folder string `json:"folder"`
268 Error string `json:"error"`
269}