Skip to content

Commit 52d7be0

Browse files
committed
mt2exm: forward RFC5322-EML blob to exmdb
With this commit, messages imported via ``gromox-eml2mt xyz.eml | gromox-mt2exm ...`` (with or without mt2exm's -D option) will now have the original RFC5322 representation recorded in the mailbox. References: GXH-155, GXF-2229
1 parent 09a2cee commit 52d7be0

File tree

3 files changed

+67
-12
lines changed

3 files changed

+67
-12
lines changed

tools/genimport.cpp

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
#include <unordered_map>
1919
#include <utility>
2020
#include <vector>
21+
#include <fmt/format.h>
22+
#include <json/value.h>
2123
#include <libHX/endian.h>
2224
#include <libHX/io.h>
2325
#include <libHX/scope.hpp>
@@ -27,6 +29,7 @@
2729
#include <gromox/exmdb_rpc.hpp>
2830
#include <gromox/ext_buffer.hpp>
2931
#include <gromox/fileio.h>
32+
#include <gromox/json.hpp>
3033
#include <gromox/list_file.hpp>
3134
#include <gromox/mapidefs.h>
3235
#include <gromox/paths.h>
@@ -309,9 +312,9 @@ int exm_permissions(eid_t fid, const std::vector<PERMISSION_DATA> &perms)
309312
return 0;
310313
}
311314

312-
int exm_deliver_msg(const char *target, MESSAGE_CONTENT *ct, unsigned int mode)
315+
int exm_deliver_msg(const char *target, MESSAGE_CONTENT *ct,
316+
const std::string &im_repr, Json::Value &&digest, unsigned int mode)
313317
{
314-
ct->proplist.erase(PidTagChangeNumber);
315318
auto ts = rop_util_current_nttime();
316319
auto ret = ct->proplist.set(PR_MESSAGE_DELIVERY_TIME, &ts);
317320
if (ret != ecSuccess)
@@ -320,12 +323,31 @@ int exm_deliver_msg(const char *target, MESSAGE_CONTENT *ct, unsigned int mode)
320323
uint32_t r32 = 0;
321324
if (mode & DELIVERY_TWOSTEP)
322325
mode &= ~(DELIVERY_DO_RULES | DELIVERY_DO_NOTIF);
326+
uint64_t change_num = 0;
327+
if (!exmdb_client->allocate_cn(g_storedir, &change_num)) {
328+
fprintf(stderr, "exm: allocate_cn(msg)[delivery] RPC failed\n");
329+
return -EIO;
330+
}
331+
auto iret = exm_set_change_keys(&ct->proplist, change_num);
332+
if (iret != 0) {
333+
fprintf(stderr, "exm: tpropval: %s\n", strerror(-iret));
334+
return iret;
335+
}
336+
auto midstr = fmt::format("{}.cn{}", time(nullptr), rop_util_get_gc_value(change_num));
337+
digest["file"] = midstr;
338+
if (!exmdb_client->imapfile_write(g_storedir, "eml",
339+
midstr.c_str(), im_repr.c_str())) {
340+
fprintf(stderr, "exm: imapfile_write RPC failed\n");
341+
return -EIO;
342+
}
343+
auto djson = json_to_str(digest);
323344
if (!exmdb_client->deliver_message(g_storedir, ENVELOPE_FROM_NULL,
324-
target, CP_ACP, mode, ct, "", &folder_id, &msg_id, &r32)) {
345+
target, CP_ACP, mode, ct, djson.c_str(), &folder_id, &msg_id, &r32)) {
325346
fprintf(stderr, "exm: deliver_message RPC failed: code %u\n",
326347
r32);
327348
return -EIO;
328349
}
350+
329351
auto dm_status = static_cast<deliver_message_result>(r32);
330352
switch (dm_status) {
331353
case deliver_message_result::result_ok:
@@ -367,7 +389,8 @@ int exm_deliver_msg(const char *target, MESSAGE_CONTENT *ct, unsigned int mode)
367389
return EXIT_SUCCESS;
368390
}
369391

370-
int exm_create_msg(uint64_t parent_fld, MESSAGE_CONTENT *ctnt)
392+
int exm_create_msg(uint64_t parent_fld, MESSAGE_CONTENT *ctnt,
393+
const std::string &im_repr, Json::Value &&digest)
371394
{
372395
uint64_t msg_id = 0, change_num = 0;
373396
if (!exmdb_client->allocate_message_id(g_storedir, parent_fld, &msg_id)) {
@@ -387,10 +410,18 @@ int exm_create_msg(uint64_t parent_fld, MESSAGE_CONTENT *ctnt)
387410
fprintf(stderr, "exm: tpropval: %s\n", strerror(-iret));
388411
return iret;
389412
}
413+
auto midstr = fmt::format("{}.cn{}", time(nullptr), rop_util_get_gc_value(change_num));
414+
digest["file"] = midstr;
415+
if (!exmdb_client->imapfile_write(g_storedir, "eml",
416+
midstr.c_str(), im_repr.c_str())) {
417+
fprintf(stderr, "exm: imapfile_write RPC failed\n");
418+
return -EIO;
419+
}
420+
auto djson = json_to_str(digest);
390421

391422
uint64_t outmid = 0, outcn = 0;
392423
if (!exmdb_client->write_message(g_storedir, CP_UTF8, parent_fld,
393-
ctnt, {}, &outmid, &outcn, &ret)) {
424+
ctnt, djson.c_str(), &outmid, &outcn, &ret)) {
394425
fprintf(stderr, "exm: write_message RPC failed\n");
395426
return -EIO;
396427
} else if (ret != ecSuccess) {

tools/genimport.hpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <string>
77
#include <unordered_map>
88
#include <vector>
9+
#include <json/value.h>
910
#include <gromox/element_data.hpp>
1011
#include <gromox/fileio.h>
1112
#include <gromox/pcl.hpp>
@@ -102,8 +103,8 @@ extern gromox::propid_t gi_resolve_namedprop(const PROPERTY_XNAME &);
102103
extern int exm_set_change_keys(TPROPVAL_ARRAY *props, eid_t cn, const BINARY *oldpcl = nullptr);
103104
extern int exm_create_folder(uint64_t parent_fld, TPROPVAL_ARRAY *props, bool o_excl, uint64_t *new_fld_id);
104105
extern int exm_permissions(eid_t, const std::vector<PERMISSION_DATA> &);
105-
extern int exm_deliver_msg(const char *target, MESSAGE_CONTENT *, unsigned int flags = 0);
106-
extern int exm_create_msg(uint64_t parent_fld, MESSAGE_CONTENT *);
106+
extern int exm_deliver_msg(const char *target, MESSAGE_CONTENT *, const std::string &, Json::Value &&, unsigned int flags = 0);
107+
extern int exm_create_msg(uint64_t parent_fld, MESSAGE_CONTENT *, const std::string &, Json::Value &&);
107108
extern int gi_setup_from_user(const char *);
108109
extern int gi_setup_from_dir(const char *);
109110
extern int gi_startup_client(unsigned int maxconn = 1);

tools/mt2exm.cpp

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,14 @@
99
#include <memory>
1010
#include <unistd.h>
1111
#include <utility>
12+
#include <json/value.h>
1213
#include <libHX/endian.h>
1314
#include <libHX/io.h>
1415
#include <libHX/option.h>
1516
#include <libHX/scope.hpp>
1617
#include <gromox/exmdb_rpc.hpp>
1718
#include <gromox/ext_buffer.hpp>
19+
#include <gromox/mail.hpp>
1820
#include <gromox/paths.h>
1921
#include <gromox/svc_loader.hpp>
2022
#include <gromox/textmaps.hpp>
@@ -302,12 +304,16 @@ static int exm_folder(const ob_desc &obd, TPROPVAL_ARRAY &props,
302304
}
303305

304306
static int exm_message(const ob_desc &obd, MESSAGE_CONTENT &ctnt,
305-
const std::string &im_std)
307+
const std::string &im_repr)
306308
{
307-
if (g_show_tree)
308-
printf("exm: Message %lxh (parent=%llxh)\n",
309+
if (g_show_tree) {
310+
printf("exm: Message %lxh (parent=%llxh)",
309311
static_cast<unsigned long>(obd.nid),
310312
static_cast<unsigned long long>(obd.parent.folder_id));
313+
if (im_repr.size() > 0)
314+
printf(" [RFC5322: %zu bytes]", im_repr.size());
315+
printf("\n");
316+
}
311317
if (g_show_tree && g_show_props)
312318
gi_print(0, ctnt, ee_get_propname);
313319
auto folder_it = g_folder_map.find(obd.parent.folder_id);
@@ -322,11 +328,27 @@ static int exm_message(const ob_desc &obd, MESSAGE_CONTENT &ctnt,
322328
tlog("adjusted properties:\n");
323329
gi_print(0, ctnt, ee_get_propname);
324330
}
331+
332+
Json::Value digest;
333+
if (im_repr.size() > 0) {
334+
MAIL imail;
335+
if (!imail.load_from_str(im_repr.data(), im_repr.size())) {
336+
fprintf(stderr, "Failed to parse RFC5322 block for message\n");
337+
return -EIO;
338+
}
339+
auto ret = imail.make_digest(digest);
340+
if (ret <= 0) {
341+
fprintf(stderr, "Failed to produce JDigest for RFC5322 block\n");
342+
return -EIO;
343+
}
344+
}
345+
325346
if (!g_do_delivery) {
326347
for (auto i = 0U; i < g_repeat_iter; ++i) {
327348
if (i > 0 && i % 1024 == 0)
328349
fprintf(stderr, "mt2exm repeat %u/%u\n", i, g_repeat_iter);
329-
auto ret = exm_create_msg(folder_it->second.fid_to, &ctnt);
350+
auto ret = exm_create_msg(folder_it->second.fid_to,
351+
&ctnt, im_repr, std::move(digest));
330352
if (ret != EXIT_SUCCESS)
331353
return ret;
332354
}
@@ -346,7 +368,8 @@ static int exm_message(const ob_desc &obd, MESSAGE_CONTENT &ctnt,
346368
for (auto i = 0U; i < g_repeat_iter; ++i) {
347369
if (i > 0 && i % 1024 == 0)
348370
fprintf(stderr, "mt2exm repeat %u/%u\n", i, g_repeat_iter);
349-
auto ret = exm_deliver_msg(g_username, &ctnt, mode);
371+
auto ret = exm_deliver_msg(g_username, &ctnt, im_repr,
372+
std::move(digest), mode);
350373
if (ret != EXIT_SUCCESS)
351374
return ret;
352375
}

0 commit comments

Comments
 (0)