1 /* Copyright (c) 2008-2018 Dovecot authors, see the included COPYING file */
2 
3 #include "lib.h"
4 #include "array.h"
5 #include "index-mail.h"
6 #include "virtual-storage.h"
7 #include "virtual-transaction.h"
8 
9 struct virtual_mail {
10 	struct index_mail imail;
11 
12 	enum mail_fetch_field wanted_fields;
13 	struct mailbox_header_lookup_ctx *wanted_headers;
14 
15 	/* temp_wanted_fields for this mail. Used only when mail doesn't have
16 	   a backend mail yet. */
17 	enum mail_fetch_field delayed_temp_fields;
18 	struct mailbox_header_lookup_ctx *delayed_temp_headers;
19 
20 	/* currently active mail */
21 	struct mail *cur_backend_mail;
22 	struct virtual_mail_index_record cur_vrec;
23 
24 	/* all allocated mails */
25 	ARRAY(struct mail *) backend_mails;
26 
27 	/* mail is lost if backend_mail doesn't point to correct mail */
28 	bool cur_lost:1;
29 };
30 
31 struct mail *
virtual_mail_alloc(struct mailbox_transaction_context * t,enum mail_fetch_field wanted_fields,struct mailbox_header_lookup_ctx * wanted_headers)32 virtual_mail_alloc(struct mailbox_transaction_context *t,
33 		   enum mail_fetch_field wanted_fields,
34 		   struct mailbox_header_lookup_ctx *wanted_headers)
35 {
36 	struct virtual_mailbox *mbox = (struct virtual_mailbox *)t->box;
37 	struct virtual_mail *vmail;
38 	pool_t mail_pool, data_pool;
39 
40 	mail_pool = pool_alloconly_create("vmail", 1024);
41 	data_pool = pool_alloconly_create("virtual index_mail", 512);
42 	vmail = p_new(mail_pool, struct virtual_mail, 1);
43 	vmail->wanted_fields = wanted_fields;
44 	vmail->wanted_headers = wanted_headers;
45 	if (vmail->wanted_headers != NULL)
46 		mailbox_header_lookup_ref(vmail->wanted_headers);
47 	/* Do not pass wanted_fields or wanted_headers to index_mail_init.
48 	   It will just cause unwanted behaviour, as we only want these
49 	   to be passed to backend mails. */
50 	index_mail_init(&vmail->imail, t, 0, NULL, mail_pool, data_pool);
51 	vmail->imail.mail.v = virtual_mail_vfuncs;
52 	i_array_init(&vmail->backend_mails, array_count(&mbox->backend_boxes));
53 	return &vmail->imail.mail.mail;
54 }
55 
virtual_mail_close(struct mail * mail)56 static void virtual_mail_close(struct mail *mail)
57 {
58 	struct virtual_mail *vmail = (struct virtual_mail *)mail;
59 	struct mail **mails;
60 	unsigned int i, count;
61 
62 	if (mail->seq != 0) {
63 		mailbox_header_lookup_unref(&vmail->delayed_temp_headers);
64 		vmail->delayed_temp_fields = 0;
65 	}
66 
67 	mails = array_get_modifiable(&vmail->backend_mails, &count);
68 	for (i = 0; i < count; i++) {
69 		struct mail_private *p = (struct mail_private *)mails[i];
70 
71 		if (vmail->imail.freeing)
72 			mail_free(&mails[i]);
73 		else
74 			p->v.close(mails[i]);
75 	}
76 	if (vmail->imail.freeing) {
77 		array_free(&vmail->backend_mails);
78 		mailbox_header_lookup_unref(&vmail->wanted_headers);
79 	}
80 	index_mail_close(mail);
81 }
82 
83 static struct mail *
backend_mail_find(struct virtual_mail * vmail,struct mailbox * box)84 backend_mail_find(struct virtual_mail *vmail, struct mailbox *box)
85 {
86 	struct mail *const *mails;
87 	unsigned int i, count;
88 
89 	mails = array_get(&vmail->backend_mails, &count);
90 	for (i = 0; i < count; i++) {
91 		if (mails[i]->box == box)
92 			return mails[i];
93 	}
94 	return NULL;
95 }
96 
backend_mail_get(struct virtual_mail * vmail,struct mail ** backend_mail_r)97 static int backend_mail_get(struct virtual_mail *vmail,
98 			    struct mail **backend_mail_r)
99 {
100 	struct mail *mail = &vmail->imail.mail.mail;
101 	struct virtual_mailbox *mbox = (struct virtual_mailbox *)mail->box;
102 	struct virtual_backend_box *bbox;
103 
104 	*backend_mail_r = NULL;
105 
106 	if (vmail->cur_backend_mail != NULL) {
107 		if (vmail->cur_lost) {
108 			mail_set_expunged(&vmail->imail.mail.mail);
109 			return -1;
110 		}
111 		*backend_mail_r = vmail->cur_backend_mail;
112 		return 0;
113 	}
114 
115 	bbox = virtual_backend_box_lookup(mbox, vmail->cur_vrec.mailbox_id);
116 	i_assert(bbox != NULL);
117 
118 	vmail->cur_backend_mail = backend_mail_find(vmail, bbox->box);
119 	if (vmail->cur_backend_mail == NULL) {
120 		if (!bbox->box->opened &&
121 		    virtual_backend_box_open(mbox, bbox) < 0) {
122 			virtual_box_copy_error(mail->box, bbox->box);
123 			return -1;
124 		}
125 		(void)virtual_mail_set_backend_mail(mail, bbox);
126 		i_assert(vmail->cur_backend_mail != NULL);
127 	}
128 	virtual_backend_box_accessed(mbox, bbox);
129 	vmail->cur_lost = !mail_set_uid(vmail->cur_backend_mail,
130 					vmail->cur_vrec.real_uid);
131 	mail->expunged = vmail->cur_lost || vmail->cur_backend_mail->expunged;
132 	if (vmail->cur_lost) {
133 		mail_set_expunged(&vmail->imail.mail.mail);
134 		return -1;
135 	}
136 	/* headers need to be converted to backend-headers, so go through
137 	   the virtual add_temp_wanted_fields() again. */
138 	mail_add_temp_wanted_fields(mail, vmail->delayed_temp_fields,
139 				    vmail->delayed_temp_headers);
140 	*backend_mail_r = vmail->cur_backend_mail;
141 	return 0;
142 }
143 
144 struct mail *
virtual_mail_set_backend_mail(struct mail * mail,struct virtual_backend_box * bbox)145 virtual_mail_set_backend_mail(struct mail *mail,
146 			      struct virtual_backend_box *bbox)
147 {
148 	struct virtual_mail *vmail = (struct virtual_mail *)mail;
149 	struct mail_private *backend_pmail;
150 	struct mailbox_transaction_context *backend_trans;
151 	struct mailbox_header_lookup_ctx *backend_headers;
152 
153 	i_assert(bbox->box->opened);
154 
155 	backend_trans = virtual_transaction_get(mail->transaction, bbox->box);
156 
157 	backend_headers = vmail->wanted_headers == NULL ? NULL :
158 		mailbox_header_lookup_init(bbox->box,
159 					   vmail->wanted_headers->name);
160 	vmail->cur_backend_mail =
161 		mail_alloc(backend_trans, vmail->wanted_fields, backend_headers);
162 	mailbox_header_lookup_unref(&backend_headers);
163 
164 	backend_pmail = (struct mail_private *)vmail->cur_backend_mail;
165 	backend_pmail->vmail = mail;
166 	array_push_back(&vmail->backend_mails, &vmail->cur_backend_mail);
167 	return vmail->cur_backend_mail;
168 }
169 
virtual_mail_set_unattached_backend_mail(struct mail * mail,struct mail * backend_mail)170 void virtual_mail_set_unattached_backend_mail(struct mail *mail,
171 					      struct mail *backend_mail)
172 {
173 	struct virtual_mail *vmail = (struct virtual_mail *)mail;
174 	struct mail_private *backend_pmail;
175 
176 	vmail->cur_backend_mail = backend_mail;
177 
178 	backend_pmail = (struct mail_private *)backend_mail;
179 	backend_pmail->vmail = mail;
180 }
181 
virtual_mail_set_seq(struct mail * mail,uint32_t seq,bool saving)182 static void virtual_mail_set_seq(struct mail *mail, uint32_t seq, bool saving)
183 {
184 	struct virtual_mail *vmail = (struct virtual_mail *)mail;
185 	struct virtual_mailbox *mbox = (struct virtual_mailbox *)mail->box;
186 	const void *data;
187 
188 	i_assert(!saving);
189 
190 	mail_index_lookup_ext(mail->transaction->view, seq,
191 			      mbox->virtual_ext_id, &data, NULL);
192 	memcpy(&vmail->cur_vrec, data, sizeof(vmail->cur_vrec));
193 
194 	index_mail_set_seq(mail, seq, saving);
195 
196 	vmail->cur_backend_mail = NULL;
197 }
198 
virtual_mail_set_uid(struct mail * mail,uint32_t uid)199 static bool virtual_mail_set_uid(struct mail *mail, uint32_t uid)
200 {
201 	uint32_t seq;
202 
203 	if (!mail_index_lookup_seq(mail->transaction->view, uid, &seq))
204 		return FALSE;
205 
206 	virtual_mail_set_seq(mail, seq, FALSE);
207 	return TRUE;
208 }
209 
virtual_mail_set_uid_cache_updates(struct mail * mail,bool set)210 static void virtual_mail_set_uid_cache_updates(struct mail *mail, bool set)
211 {
212 	struct virtual_mail *vmail = (struct virtual_mail *)mail;
213 	struct mail *backend_mail;
214 	struct mail_private *p;
215 
216 	if (backend_mail_get(vmail, &backend_mail) < 0)
217 		return;
218 	p = (struct mail_private *)backend_mail;
219 	p->v.set_uid_cache_updates(backend_mail, set);
220 }
221 
virtual_mail_prefetch(struct mail * mail)222 static bool virtual_mail_prefetch(struct mail *mail)
223 {
224 	struct virtual_mail *vmail = (struct virtual_mail *)mail;
225 	struct mail *backend_mail;
226 	struct mail_private *p;
227 
228 	if (backend_mail_get(vmail, &backend_mail) < 0)
229 		return TRUE;
230 	p = (struct mail_private *)backend_mail;
231 	return p->v.prefetch(backend_mail);
232 }
233 
virtual_mail_precache(struct mail * mail)234 static int virtual_mail_precache(struct mail *mail)
235 {
236 	struct virtual_mail *vmail = (struct virtual_mail *)mail;
237 	struct mail *backend_mail;
238 	struct mail_private *p;
239 
240 	if (backend_mail_get(vmail, &backend_mail) < 0)
241 		return -1;
242 	p = (struct mail_private *)backend_mail;
243 	return p->v.precache(backend_mail);
244 }
245 
246 static void
virtual_mail_add_temp_wanted_fields(struct mail * mail,enum mail_fetch_field fields,struct mailbox_header_lookup_ctx * headers)247 virtual_mail_add_temp_wanted_fields(struct mail *mail,
248 				    enum mail_fetch_field fields,
249 				    struct mailbox_header_lookup_ctx *headers)
250 {
251 	struct virtual_mail *vmail = (struct virtual_mail *)mail;
252 	struct mail *backend_mail;
253 	struct mailbox_header_lookup_ctx *backend_headers, *new_headers;
254 
255 	if (mail->seq == 0) {
256 		/* No mail set yet. Delay until it is set. */
257 		vmail->delayed_temp_fields |= fields;
258 		if (vmail->delayed_temp_headers == NULL)
259 			vmail->delayed_temp_headers = headers;
260 		else {
261 			new_headers = mailbox_header_lookup_merge(
262 				vmail->delayed_temp_headers, headers);
263 			mailbox_header_lookup_unref(&vmail->delayed_temp_headers);
264 			vmail->delayed_temp_headers = new_headers;
265 		}
266 		return;
267 	}
268 
269 	if (backend_mail_get(vmail, &backend_mail) < 0)
270 		return;
271 	/* convert header indexes to backend mailbox's header indexes */
272 	backend_headers = headers == NULL ? NULL :
273 		mailbox_header_lookup_init(backend_mail->box, headers->name);
274 	mail_add_temp_wanted_fields(backend_mail, fields, backend_headers);
275 	mailbox_header_lookup_unref(&backend_headers);
276 }
277 
278 static int
virtual_mail_get_parts(struct mail * mail,struct message_part ** parts_r)279 virtual_mail_get_parts(struct mail *mail, struct message_part **parts_r)
280 {
281 	struct virtual_mail *vmail = (struct virtual_mail *)mail;
282 	struct mail *backend_mail;
283 
284 	if (backend_mail_get(vmail, &backend_mail) < 0)
285 		return -1;
286 	if (mail_get_parts(backend_mail, parts_r) < 0) {
287 		virtual_box_copy_error(mail->box, backend_mail->box);
288 		return -1;
289 	}
290 	return 0;
291 }
292 
293 static int
virtual_mail_get_date(struct mail * mail,time_t * date_r,int * timezone_r)294 virtual_mail_get_date(struct mail *mail, time_t *date_r, int *timezone_r)
295 {
296 	struct virtual_mail *vmail = (struct virtual_mail *)mail;
297 	struct mail *backend_mail;
298 	int tz;
299 
300 	if (timezone_r == NULL)
301 		timezone_r = &tz;
302 
303 	if (backend_mail_get(vmail, &backend_mail) < 0)
304 		return -1;
305 	if (mail_get_date(backend_mail, date_r, timezone_r) < 0) {
306 		virtual_box_copy_error(mail->box, backend_mail->box);
307 		return -1;
308 	}
309 	return 0;
310 }
311 
virtual_mail_get_received_date(struct mail * mail,time_t * date_r)312 static int virtual_mail_get_received_date(struct mail *mail, time_t *date_r)
313 {
314 	struct virtual_mail *vmail = (struct virtual_mail *)mail;
315 	struct mail *backend_mail;
316 
317 	if (backend_mail_get(vmail, &backend_mail) < 0)
318 		return -1;
319 	if (mail_get_received_date(backend_mail, date_r) < 0) {
320 		virtual_box_copy_error(mail->box, backend_mail->box);
321 		return -1;
322 	}
323 	return 0;
324 }
325 
virtual_mail_get_save_date(struct mail * mail,time_t * date_r)326 static int virtual_mail_get_save_date(struct mail *mail, time_t *date_r)
327 {
328 	struct virtual_mail *vmail = (struct virtual_mail *)mail;
329 	struct mail *backend_mail;
330 	int ret;
331 
332 	if (backend_mail_get(vmail, &backend_mail) < 0)
333 		return -1;
334 	ret = mail_get_save_date(backend_mail, date_r);
335 	if (ret < 0)
336 		virtual_box_copy_error(mail->box, backend_mail->box);
337 	return ret;
338 }
339 
virtual_mail_get_virtual_mail_size(struct mail * mail,uoff_t * size_r)340 static int virtual_mail_get_virtual_mail_size(struct mail *mail, uoff_t *size_r)
341 {
342 	struct virtual_mail *vmail = (struct virtual_mail *)mail;
343 	struct mail *backend_mail;
344 
345 	if (backend_mail_get(vmail, &backend_mail) < 0)
346 		return -1;
347 	if (mail_get_virtual_size(backend_mail, size_r) < 0) {
348 		virtual_box_copy_error(mail->box, backend_mail->box);
349 		return -1;
350 	}
351 	return 0;
352 }
353 
virtual_mail_get_physical_size(struct mail * mail,uoff_t * size_r)354 static int virtual_mail_get_physical_size(struct mail *mail, uoff_t *size_r)
355 {
356 	struct virtual_mail *vmail = (struct virtual_mail *)mail;
357 	struct mail *backend_mail;
358 
359 	if (backend_mail_get(vmail, &backend_mail) < 0)
360 		return -1;
361 	if (mail_get_physical_size(backend_mail, size_r) < 0) {
362 		virtual_box_copy_error(mail->box, backend_mail->box);
363 		return -1;
364 	}
365 	return 0;
366 }
367 
368 static int
virtual_mail_get_first_header(struct mail * mail,const char * field,bool decode_to_utf8,const char ** value_r)369 virtual_mail_get_first_header(struct mail *mail, const char *field,
370 			      bool decode_to_utf8, const char **value_r)
371 {
372 	struct virtual_mail *vmail = (struct virtual_mail *)mail;
373 	struct mail *backend_mail;
374 	struct mail_private *p;
375 	int ret;
376 
377 	if (backend_mail_get(vmail, &backend_mail) < 0)
378 		return -1;
379 	p = (struct mail_private *)backend_mail;
380 	ret = p->v.get_first_header(backend_mail, field,
381 				    decode_to_utf8, value_r);
382 	if (ret < 0) {
383 		virtual_box_copy_error(mail->box, backend_mail->box);
384 		return -1;
385 	}
386 	return ret;
387 }
388 
389 static int
virtual_mail_get_headers(struct mail * mail,const char * field,bool decode_to_utf8,const char * const ** value_r)390 virtual_mail_get_headers(struct mail *mail, const char *field,
391 			 bool decode_to_utf8, const char *const **value_r)
392 {
393 	struct virtual_mail *vmail = (struct virtual_mail *)mail;
394 	struct mail *backend_mail;
395 	struct mail_private *p;
396 
397 	if (backend_mail_get(vmail, &backend_mail) < 0)
398 		return -1;
399 	p = (struct mail_private *)backend_mail;
400 	if (p->v.get_headers(backend_mail, field, decode_to_utf8, value_r) < 0) {
401 		virtual_box_copy_error(mail->box, backend_mail->box);
402 		return -1;
403 	}
404 	return 0;
405 }
406 
407 static int
virtual_mail_get_header_stream(struct mail * mail,struct mailbox_header_lookup_ctx * headers,struct istream ** stream_r)408 virtual_mail_get_header_stream(struct mail *mail,
409 			       struct mailbox_header_lookup_ctx *headers,
410 			       struct istream **stream_r)
411 {
412 	struct virtual_mail *vmail = (struct virtual_mail *)mail;
413 	struct mail *backend_mail;
414 	struct mailbox_header_lookup_ctx *backend_headers;
415 	int ret;
416 
417 	if (backend_mail_get(vmail, &backend_mail) < 0)
418 		return -1;
419 
420 	backend_headers = mailbox_header_lookup_init(backend_mail->box,
421 						     headers->name);
422 	ret = mail_get_header_stream(backend_mail, backend_headers, stream_r);
423 	mailbox_header_lookup_unref(&backend_headers);
424 	if (ret < 0) {
425 		virtual_box_copy_error(mail->box, backend_mail->box);
426 		return -1;
427 	}
428 	return 0;
429 }
430 
431 static int
virtual_mail_get_stream(struct mail * mail,bool get_body,struct message_size * hdr_size,struct message_size * body_size,struct istream ** stream_r)432 virtual_mail_get_stream(struct mail *mail, bool get_body,
433 			struct message_size *hdr_size,
434 			struct message_size *body_size,
435 			struct istream **stream_r)
436 {
437 	struct virtual_mail *vmail = (struct virtual_mail *)mail;
438 	struct mail_private *vp = (struct mail_private *)mail;
439 	struct mail *backend_mail;
440 	const char *reason = t_strdup_printf("virtual mailbox %s: Opened mail UID=%u: %s",
441 					     mailbox_get_vname(mail->box), mail->uid, vp->get_stream_reason);
442 	int ret;
443 
444 	if (backend_mail_get(vmail, &backend_mail) < 0)
445 		return -1;
446 
447 	if (get_body) {
448 		ret = mail_get_stream_because(backend_mail, hdr_size, body_size,
449 					      reason, stream_r);
450 	} else {
451 		ret = mail_get_hdr_stream_because(backend_mail, hdr_size,
452 						  reason, stream_r);
453 	}
454 
455 	if (ret < 0) {
456 		virtual_box_copy_error(mail->box, backend_mail->box);
457 		return -1;
458 	}
459 	return 0;
460 }
461 
462 static int
virtual_mail_get_binary_stream(struct mail * mail,const struct message_part * part,bool include_hdr,uoff_t * size_r,unsigned int * lines_r,bool * binary_r,struct istream ** stream_r)463 virtual_mail_get_binary_stream(struct mail *mail,
464 			       const struct message_part *part,
465 			       bool include_hdr, uoff_t *size_r,
466 			       unsigned int *lines_r, bool *binary_r,
467 			       struct istream **stream_r)
468 {
469 	struct virtual_mail *vmail = (struct virtual_mail *)mail;
470 	struct mail *backend_mail;
471 
472 	if (backend_mail_get(vmail, &backend_mail) < 0)
473 		return -1;
474 
475 	struct mail_private *p = (struct mail_private *)backend_mail;
476 	if (p->v.get_binary_stream(backend_mail, part, include_hdr,
477 				   size_r, lines_r, binary_r, stream_r) < 0) {
478 		virtual_box_copy_error(mail->box, backend_mail->box);
479 		return -1;
480 	}
481 	return 0;
482 }
483 
484 static int
virtual_mail_get_special(struct mail * mail,enum mail_fetch_field field,const char ** value_r)485 virtual_mail_get_special(struct mail *mail, enum mail_fetch_field field,
486 			 const char **value_r)
487 {
488 	struct virtual_mail *vmail = (struct virtual_mail *)mail;
489 	struct mail *backend_mail;
490 
491 	if (backend_mail_get(vmail, &backend_mail) < 0)
492 		return -1;
493 	if (mail_get_special(backend_mail, field, value_r) < 0) {
494 		virtual_box_copy_error(mail->box, backend_mail->box);
495 		return -1;
496 	}
497 	return 0;
498 }
499 
virtual_mail_get_backend_mail(struct mail * mail,struct mail ** real_mail_r)500 static int virtual_mail_get_backend_mail(struct mail *mail,
501 					 struct mail **real_mail_r)
502 {
503 	struct virtual_mail *vmail = (struct virtual_mail *)mail;
504 	struct mail *backend_mail;
505 
506 	if (backend_mail_get(vmail, &backend_mail) < 0)
507 		return -1;
508 
509 	if (mail_get_backend_mail(backend_mail, real_mail_r) < 0)
510 		return -1;
511 	return 0;
512 }
513 
virtual_mail_update_pop3_uidl(struct mail * mail,const char * uidl)514 static void virtual_mail_update_pop3_uidl(struct mail *mail, const char *uidl)
515 {
516 	struct virtual_mail *vmail = (struct virtual_mail *)mail;
517 	struct mail *backend_mail;
518 
519 	if (backend_mail_get(vmail, &backend_mail) < 0)
520 		return;
521 	mail_update_pop3_uidl(backend_mail, uidl);
522 }
523 
virtual_mail_expunge(struct mail * mail)524 static void virtual_mail_expunge(struct mail *mail)
525 {
526 	struct virtual_mail *vmail = (struct virtual_mail *)mail;
527 	struct mail *backend_mail;
528 
529 	if (backend_mail_get(vmail, &backend_mail) < 0)
530 		return;
531 	mail_expunge(backend_mail);
532 }
533 
534 static void
virtual_mail_set_cache_corrupted(struct mail * mail,enum mail_fetch_field field,const char * reason)535 virtual_mail_set_cache_corrupted(struct mail *mail,
536 				 enum mail_fetch_field field,
537 				 const char *reason)
538 {
539 	struct virtual_mail *vmail = (struct virtual_mail *)mail;
540 	struct mail *backend_mail;
541 
542 	if (backend_mail_get(vmail, &backend_mail) < 0)
543 		return;
544 	mail_set_cache_corrupted(backend_mail, field, reason);
545 }
546 
547 struct mail_vfuncs virtual_mail_vfuncs = {
548 	virtual_mail_close,
549 	index_mail_free,
550 	virtual_mail_set_seq,
551 	virtual_mail_set_uid,
552 	virtual_mail_set_uid_cache_updates,
553 	virtual_mail_prefetch,
554 	virtual_mail_precache,
555 	virtual_mail_add_temp_wanted_fields,
556 
557 	index_mail_get_flags,
558 	index_mail_get_keywords,
559 	index_mail_get_keyword_indexes,
560 	index_mail_get_modseq,
561 	index_mail_get_pvt_modseq,
562 	virtual_mail_get_parts,
563 	virtual_mail_get_date,
564 	virtual_mail_get_received_date,
565 	virtual_mail_get_save_date,
566 	virtual_mail_get_virtual_mail_size,
567 	virtual_mail_get_physical_size,
568 	virtual_mail_get_first_header,
569 	virtual_mail_get_headers,
570 	virtual_mail_get_header_stream,
571 	virtual_mail_get_stream,
572 	virtual_mail_get_binary_stream,
573 	virtual_mail_get_special,
574 	virtual_mail_get_backend_mail,
575 	index_mail_update_flags,
576 	index_mail_update_keywords,
577 	index_mail_update_modseq,
578 	index_mail_update_pvt_modseq,
579 	virtual_mail_update_pop3_uidl,
580 	virtual_mail_expunge,
581 	virtual_mail_set_cache_corrupted,
582 	NULL,
583 };
584