Sending Asterisk 1.4 voicemails to multiple emails

Here’s the complicated way to get Asterisk sending voicemail notifications to multiple email addresses. (The easy way? Use group mailboxes and/or sendmail aliases.) Once this modified module is compiled and installed, multiple addresses in voicemail.conf can be separated by a pipe character.

You can apply the patch and rebuild Asterisk as usual, or just build the single module manually which I do like this:

cd /usr/src/asterisk
patch -bp0 < ~/vm_patch.diff
gcc -pipe -Wall -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -g3 -Iinclude -I../include -D_REENTRANT -D_GNU_SOURCE -O6 -march=i686 -fomit-frame-pointer -Wno-missing-prototypes -Wno-missing-declarations -DCRYPTO -fPIC -c -o apps/app_voicemail.o apps/app_voicemail.c
gcc -shared -Xlinker -x -o apps/app_voicemail.so apps/app_voicemail.o
cp /usr/lib/asterisk/modules/app_voicemail.so /usr/lib/asterisk/modules/app_voicemail.so.orig
cp /usr/src/asterisk/apps/app_voicemail.so /usr/lib/asterisk/modules/app_voicemail.so

cd /usr/src/asterisk patch -bp0 < ~/vm_patch.diff gcc -pipe -Wall -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -g3 -Iinclude -I../include -D_REENTRANT -D_GNU_SOURCE -O6 -march=i686 -fomit-frame-pointer -Wno-missing-prototypes -Wno-missing-declarations -DCRYPTO -fPIC -c -o apps/app_voicemail.o apps/app_voicemail.c gcc -shared -Xlinker -x -o apps/app_voicemail.so apps/app_voicemail.o cp /usr/lib/asterisk/modules/app_voicemail.so /usr/lib/asterisk/modules/app_voicemail.so.orig cp /usr/src/asterisk/apps/app_voicemail.so /usr/lib/asterisk/modules/app_voicemail.so

This patch file is against Asterisk 1.4.42; you’re likely running a different version so proceed with caution.

--- apps/app_voicemail.c.orig	2011-05-04 12:08:50.000000000 -0400
+++ apps/app_voicemail.c	2011-09-06 11:58:56.000000000 -0400
@@ -53,7 +53,9 @@
 #include "asterisk.h"
 
 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 316707 $")
-
+#ifndef AST_MODULE
+	#define AST_MODULE "app_voicemail"
+#endif
 #include <stdlib.h>
 #include <errno.h>
 #include <unistd.h>
@@ -505,11 +507,11 @@
 static int my_umask;
 
 #if ODBC_STORAGE
-#define tdesc "Comedian Mail (Voicemail System) with ODBC Storage"
+#define tdesc "Comedian Mail (Voicemail System) with ODBC Storage - multimail patch"
 #elif IMAP_STORAGE
-#define tdesc "Comedian Mail (Voicemail System) with IMAP Storage"
+#define tdesc "Comedian Mail (Voicemail System) with IMAP Storage - multimail patch"
 #else
-#define tdesc "Comedian Mail (Voicemail System)"
+#define tdesc "Comedian Mail (Voicemail System) - multimail patch"
 #endif
 
 static char userscontext[AST_MAX_EXTENSION] = "default";
@@ -3407,6 +3409,9 @@
 	struct tm tm;
 	char *passdata = NULL, *passdata2;
 	size_t len_passdata = 0, len_passdata2, tmplen;
+	char *email;
+	char *tmp;
+	char *addressdelimiter = "|";
 
 	/* One alloca for multiple fields */
 	len_passdata2 = strlen(vmu->fullname);
@@ -3469,19 +3474,30 @@
 	} else
 		fprintf(p, "From: Asterisk PBX <%s>" ENDL, who);
 
-	if (check_mime(vmu->fullname)) {
-		int first_line = 1;
-		char *ptr;
-		encode_mime_str(vmu->fullname, passdata2, len_passdata2, strlen("To: "), strlen(vmu->email) + 3);
-		while ((ptr = strchr(passdata2, ' '))) {
-			*ptr = '\0';
-			fprintf(p, "%s %s" ENDL, first_line ? "To:" : "", passdata2);
-			first_line = 0;
-			passdata2 = ptr + 1;
+	if (*addressdelimiter && strchr(vmu->email, *addressdelimiter)) {
+		fprintf(p, "To: ");
+		tmp = strdupa(vmu->email);
+		email = strtok(tmp, addressdelimiter);
+		while (email) {
+			fprintf(p, "%s, ", email);
+			email = strtok(NULL, addressdelimiter);
 		}
-		fprintf(p, "%s %s <%s>" ENDL, first_line ? "To:" : "", passdata2, vmu->email);
+		fprintf(p, ENDL);
 	} else {
-		fprintf(p, "To: %s <%s>" ENDL, quote(vmu->fullname, passdata2, len_passdata2), vmu->email);
+		if (check_mime(vmu->fullname)) {
+			int first_line = 1;
+			char *ptr;
+			encode_mime_str(vmu->fullname, passdata2, len_passdata2, strlen("To: "), strlen(vmu->email) + 3);
+			while ((ptr = strchr(passdata2, ' '))) {
+				*ptr = '\0';
+				fprintf(p, "%s %s" ENDL, first_line ? "To:" : "", passdata2);
+				first_line = 0;
+				passdata2 = ptr + 1;
+			}
+			fprintf(p, "%s %s <%s>" ENDL, first_line ? "To:" : "", passdata2, vmu->email);
+		} else {
+			fprintf(p, "To: %s <%s>" ENDL, quote(vmu->fullname, passdata2, len_passdata2), vmu->email);
+		}
 	}
 	if (emailsubject) {
 		struct ast_channel *ast;

--- apps/app_voicemail.c.orig 2011-05-04 12:08:50.000000000 -0400 +++ apps/app_voicemail.c 2011-09-06 11:58:56.000000000 -0400 @@ -53,7 +53,9 @@ #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision: 316707 $") - +#ifndef AST_MODULE + #define AST_MODULE "app_voicemail" +#endif #include <stdlib.h> #include <errno.h> #include <unistd.h> @@ -505,11 +507,11 @@ static int my_umask; #if ODBC_STORAGE -#define tdesc "Comedian Mail (Voicemail System) with ODBC Storage" +#define tdesc "Comedian Mail (Voicemail System) with ODBC Storage - multimail patch" #elif IMAP_STORAGE -#define tdesc "Comedian Mail (Voicemail System) with IMAP Storage" +#define tdesc "Comedian Mail (Voicemail System) with IMAP Storage - multimail patch" #else -#define tdesc "Comedian Mail (Voicemail System)" +#define tdesc "Comedian Mail (Voicemail System) - multimail patch" #endif static char userscontext[AST_MAX_EXTENSION] = "default"; @@ -3407,6 +3409,9 @@ struct tm tm; char *passdata = NULL, *passdata2; size_t len_passdata = 0, len_passdata2, tmplen; + char *email; + char *tmp; + char *addressdelimiter = "|"; /* One alloca for multiple fields */ len_passdata2 = strlen(vmu->fullname); @@ -3469,19 +3474,30 @@ } else fprintf(p, "From: Asterisk PBX <%s>" ENDL, who); - if (check_mime(vmu->fullname)) { - int first_line = 1; - char *ptr; - encode_mime_str(vmu->fullname, passdata2, len_passdata2, strlen("To: "), strlen(vmu->email) + 3); - while ((ptr = strchr(passdata2, ' '))) { - *ptr = '\0'; - fprintf(p, "%s %s" ENDL, first_line ? "To:" : "", passdata2); - first_line = 0; - passdata2 = ptr + 1; + if (*addressdelimiter && strchr(vmu->email, *addressdelimiter)) { + fprintf(p, "To: "); + tmp = strdupa(vmu->email); + email = strtok(tmp, addressdelimiter); + while (email) { + fprintf(p, "%s, ", email); + email = strtok(NULL, addressdelimiter); } - fprintf(p, "%s %s <%s>" ENDL, first_line ? "To:" : "", passdata2, vmu->email); + fprintf(p, ENDL); } else { - fprintf(p, "To: %s <%s>" ENDL, quote(vmu->fullname, passdata2, len_passdata2), vmu->email); + if (check_mime(vmu->fullname)) { + int first_line = 1; + char *ptr; + encode_mime_str(vmu->fullname, passdata2, len_passdata2, strlen("To: "), strlen(vmu->email) + 3); + while ((ptr = strchr(passdata2, ' '))) { + *ptr = '\0'; + fprintf(p, "%s %s" ENDL, first_line ? "To:" : "", passdata2); + first_line = 0; + passdata2 = ptr + 1; + } + fprintf(p, "%s %s <%s>" ENDL, first_line ? "To:" : "", passdata2, vmu->email); + } else { + fprintf(p, "To: %s <%s>" ENDL, quote(vmu->fullname, passdata2, len_passdata2), vmu->email); + } } if (emailsubject) { struct ast_channel *ast;

Sample entry in voicemail.conf:

202 => 1234,Gina Smart,gina@widgets-inc.biz|gina@ginas.home,,attachfmt=wav|delete=yes