From eef5a0b7bf1b0c6687e357ed8ffb75dc864ed521 Mon Sep 17 00:00:00 2001 From: Mike Bradeen Date: Thu, 29 Jun 2023 12:20:53 -0600 Subject: [PATCH] Adds manager actions to allow move/remove/forward individual messages in a particular mailbox folder. The forward command can be used to copy a message within a mailbox or to another mailbox. Also adds a VoicemailBoxSummarry, required to retrieve message ID's. Resolves: #181 UserNote: The following manager actions have been added VoicemailBoxSummary - Generate message list for a given mailbox VoicemailRemove - Remove a message from a mailbox folder VoicemailMove - Move a message from one folder to another within a mailbox VoicemailForward - Copy a message from one folder in one mailbox to another folder in another or the same mailbox. --- apps/app_voicemail.c | 326 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 326 insertions(+) diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c index 263348a794..644f078f11 100644 --- a/apps/app_voicemail.c +++ b/apps/app_voicemail.c @@ -445,6 +445,107 @@ Otherwise, only a single mailbox will be polled for changes. + + + Show the mailbox contents of given voicemail user. + + + + + The context you want to check. + + + The mailbox you want to check. + + + + Retrieves the contents of the given voicemail user's mailbox. + + + + + Move Voicemail between mailbox folders of given user. + + + + + The context of the Voicemail you want to move. + + + The mailbox of the Voicemail you want to move. + + + The Folder containing the Voicemail you want to move. + + + The ID of the Voicemail you want to move. + + + The Folder you want to move the Voicemail to. + + + + Move a given Voicemail between Folders within a user's Mailbox. + + + + + Remove Voicemail from mailbox folder. + + + + + The context of the Voicemail you want to remove. + + + The mailbox of the Voicemail you want to remove. + + + The Folder containing the Voicemail you want to remove. + + + The ID of the Voicemail you want to remove. + + + + Remove a given Voicemail from a user's Mailbox Folder. + + + + + Forward Voicemail from one mailbox folder to another between given users. + + + + + The context of the Voicemail you want to move. + + + The mailbox of the Voicemail you want to move. + + + The Folder containing the Voicemail you want to move. + + + The ID of the Voicemail you want to move. + + + The context you want to move the Voicemail to. + + + The mailbox you want to move the Voicemail to. + + + The Folder you want to move the Voicemail to. + + + + Forward a given Voicemail from a user's Mailbox Folder to + another user's Mailbox Folder. Can be used to copy between + Folders within a mailbox by specifying the to context and user + as the same as the from. + + ***/ #ifdef IMAP_STORAGE @@ -1051,6 +1152,7 @@ static const char *substitute_escapes(const char *value); static int message_range_and_existence_check(struct vm_state *vms, const char *msg_ids [], size_t num_msgs, int *msg_nums, struct ast_vm_user *vmu); static void notify_new_state(struct ast_vm_user *vmu); static int append_vmu_info_astman(struct mansession *s, struct ast_vm_user *vmu, const char* event_name, const char* actionid); +static int append_vmbox_info_astman(struct mansession *s, const struct message *m, struct ast_vm_user *vmu, const char* event_name, const char* actionid); /*! @@ -13656,6 +13758,65 @@ static int append_vmu_info_astman( } + +/*! + * \brief Append vmbox info string into given astman with event_name. + * \return 0 if unable to append details, 1 otherwise. +*/ +static int append_vmbox_info_astman( + struct mansession *s, + const struct message *m, + struct ast_vm_user *vmu, + const char* event_name, + const char* actionid) +{ + struct ast_vm_mailbox_snapshot *mailbox_snapshot; + struct ast_vm_msg_snapshot *msg; + int nummessages = 0; + + /* Take a snapshot of the mailbox */ + mailbox_snapshot = ast_vm_mailbox_snapshot_create(vmu->mailbox, vmu->context, NULL, 0, AST_VM_SNAPSHOT_SORT_BY_ID, 0); + if (!mailbox_snapshot) { + ast_log(LOG_ERROR, "Could not append voicemail box info for box %s@%s.", + vmu->mailbox, vmu->context); + return 0; + } + + astman_send_listack(s, m, "Voicemail box detail will follow", "start"); + /* walk through each folder's contents and append info for each message */ + for (int i = 0; i < mailbox_snapshot->folders; i++) { + AST_LIST_TRAVERSE(&((mailbox_snapshot)->snapshots[i]), msg, msg) { + astman_append(s, + "Event: %s\r\n" + "%s" + "Folder: %s\r\n" + "CallerID: %s\r\n" + "Date: %s\r\n" + "Duration: %s\r\n" + "Flag: %s\r\n" + "ID: %s\r\n" + "\r\n", + event_name, + actionid, + msg->folder_name, + msg->callerid, + msg->origdate, + msg->duration, + msg->flag, + msg->msg_id + ); + nummessages++; + } + } + + /* done, destroy. */ + mailbox_snapshot = ast_vm_mailbox_snapshot_destroy(mailbox_snapshot); + astman_send_list_complete_start(s, m, "VoicemailBoxDetailComplete", nummessages); + astman_send_list_complete_end(s); + + return 1; +} + static int manager_match_mailbox(struct ast_mwi_state *mwi_state, void *data) { const char *context = astman_get_header(data, "Context"); @@ -13781,6 +13942,163 @@ static int manager_list_voicemail_users(struct mansession *s, const struct messa return RESULT_SUCCESS; } +static int manager_get_mailbox_summary(struct mansession *s, const struct message *m) +{ + struct ast_vm_user *vmu = NULL; + const char *id = astman_get_header(m, "ActionID"); + char actionid[128]; + struct ast_vm_user svm; + + const char *context = astman_get_header(m, "Context"); + const char *mailbox = astman_get_header(m, "Mailbox"); + + if ((ast_strlen_zero(context) || ast_strlen_zero(mailbox))) { + astman_send_error(s, m, "Need 'Context' and 'Mailbox' parameters."); + return 0; + } + + actionid[0] = '\0'; + if (!ast_strlen_zero(id)) { + snprintf(actionid, sizeof(actionid), "ActionID: %s\r\n", id); + } + + /* find user */ + memset(&svm, 0, sizeof(svm)); + vmu = find_user(&svm, context, mailbox); + if (!vmu) { + /* could not find it */ + astman_send_ack(s, m, "There is no voicemail user matching the given user."); + return 0; + } + + /* Append the mailbox details */ + if (!append_vmbox_info_astman(s, m, vmu, "VoicemailBoxDetail", actionid)) { + astman_send_error(s, m, "Unable to get mailbox info for the given user."); + } + + free_user(vmu); + return 0; +} + +static int manager_voicemail_move(struct mansession *s, const struct message *m) +{ + const char *mailbox = astman_get_header(m, "Mailbox"); + const char *context = astman_get_header(m, "Context"); + const char *from_folder = astman_get_header(m, "Folder"); + const char *id[] = { astman_get_header(m, "ID") }; + const char *to_folder = astman_get_header(m, "ToFolder"); + + if (ast_strlen_zero(mailbox)) { + astman_send_error(s, m, "Mailbox not specified, required"); + return 0; + } + if (ast_strlen_zero(context)) { + astman_send_error(s, m, "Context not specified, required"); + return 0; + } + if (ast_strlen_zero(from_folder)) { + astman_send_error(s, m, "Folder not specified, required"); + return 0; + } + if (ast_strlen_zero(id[0])) { + astman_send_error(s, m, "ID not specified, required"); + return 0; + } + if (ast_strlen_zero(to_folder)) { + astman_send_error(s, m, "ToFolder not specified, required"); + return 0; + } + + if (vm_msg_move(mailbox, context, 1, from_folder, id, to_folder)) { + astman_send_ack(s, m, "Message move failed\n"); + } else { + astman_send_ack(s, m, "Message move successful\n"); + } + + return 0; +} + +static int manager_voicemail_remove(struct mansession *s, const struct message *m) +{ + const char *mailbox = astman_get_header(m, "Mailbox"); + const char *context = astman_get_header(m, "Context"); + const char *folder = astman_get_header(m, "Folder"); + const char *id[] = { astman_get_header(m, "ID") }; + + if (ast_strlen_zero(mailbox)) { + astman_send_error(s, m, "Mailbox not specified, required"); + return 0; + } + if (ast_strlen_zero(context)) { + astman_send_error(s, m, "Context not specified, required"); + return 0; + } + if (ast_strlen_zero(folder)) { + astman_send_error(s, m, "Folder not specified, required"); + return 0; + } + if (ast_strlen_zero(id[0])) { + astman_send_error(s, m, "ID not specified, required"); + return 0; + } + + if (vm_msg_remove(mailbox, context, 1, folder, id)) { + astman_send_ack(s, m, "Message remove failed\n"); + } else { + astman_send_ack(s, m, "Message remove successful\n"); + } + + return 0; +} + +static int manager_voicemail_forward(struct mansession *s, const struct message *m) +{ + const char *from_mailbox = astman_get_header(m, "Mailbox"); + const char *from_context = astman_get_header(m, "Context"); + const char *from_folder = astman_get_header(m, "Folder"); + const char *id[] = { astman_get_header(m, "ID") }; + const char *to_mailbox = astman_get_header(m, "ToMailbox"); + const char *to_context = astman_get_header(m, "ToContext"); + const char *to_folder = astman_get_header(m, "ToFolder"); + + if (ast_strlen_zero(from_mailbox)) { + astman_send_error(s, m, "Mailbox not specified, required"); + return 0; + } + if (ast_strlen_zero(from_context)) { + astman_send_error(s, m, "Context not specified, required"); + return 0; + } + if (ast_strlen_zero(from_folder)) { + astman_send_error(s, m, "Folder not specified, required"); + return 0; + } + if (ast_strlen_zero(id[0])) { + astman_send_error(s, m, "ID not specified, required"); + return 0; + } + if (ast_strlen_zero(to_mailbox)) { + astman_send_error(s, m, "ToMailbox not specified, required"); + return 0; + } + if (ast_strlen_zero(to_context)) { + astman_send_error(s, m, "ToContext not specified, required"); + return 0; + } + if (ast_strlen_zero(to_folder)) { + astman_send_error(s, m, "ToFolder not specified, required"); + return 0; + } + + if (vm_msg_forward(from_mailbox, from_context, from_folder, to_mailbox, to_context, to_folder, 1, id, 0)) { + astman_send_ack(s, m, "Message forward failed\n"); + } else { + astman_send_ack(s, m, "Message forward successful\n"); + } + + return 0; +} + /*! \brief Free the users structure. */ static void free_vm_users(void) { @@ -15375,6 +15693,10 @@ static int unload_module(void) res |= ast_manager_unregister("VoicemailUsersList"); res |= ast_manager_unregister("VoicemailUserStatus"); res |= ast_manager_unregister("VoicemailRefresh"); + res |= ast_manager_unregister("VoicemailBoxSummary"); + res |= ast_manager_unregister("VoicemailMove"); + res |= ast_manager_unregister("VoicemailRemove"); + res |= ast_manager_unregister("VoicemailForward"); #ifdef TEST_FRAMEWORK res |= AST_TEST_UNREGISTER(test_voicemail_vmsayname); res |= AST_TEST_UNREGISTER(test_voicemail_msgcount); @@ -15502,6 +15824,10 @@ static int load_module(void) res |= ast_manager_register_xml("VoicemailUsersList", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, manager_list_voicemail_users); res |= ast_manager_register_xml("VoicemailUserStatus", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, manager_status_voicemail_user); res |= ast_manager_register_xml("VoicemailRefresh", EVENT_FLAG_USER, manager_voicemail_refresh); + res |= ast_manager_register_xml("VoicemailBoxSummary", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, manager_get_mailbox_summary); + res |= ast_manager_register_xml("VoicemailMove", EVENT_FLAG_USER, manager_voicemail_move); + res |= ast_manager_register_xml("VoicemailRemove", EVENT_FLAG_USER, manager_voicemail_remove); + res |= ast_manager_register_xml("VoicemailForward", EVENT_FLAG_USER, manager_voicemail_forward); #ifdef TEST_FRAMEWORK res |= AST_TEST_REGISTER(test_voicemail_vmsayname); res |= AST_TEST_REGISTER(test_voicemail_msgcount); -- 2.47.2