diff --git a/CHANGES b/CHANGES
index 431efd4867c6660a048d22da44e00768ad26294d..8a387244d7d22a68b5dc88e45abd22b42f71f079 100644
--- a/CHANGES
+++ b/CHANGES
@@ -50,6 +50,8 @@ Applications
    to cycle through the next avaliable channel.  By default this is still '*'.
  * Added x() option to app_chanspy.  This option allows DTMF to be set to
    exit the application.
+ * The Voicemail application has been improved to automatically ignore messages
+   that only contain silence.
 
 Dialplan Functions
 ------------------
diff --git a/main/app.c b/main/app.c
index eacefabd06ca52040c23107d38b4fbbbdcf8aa1a..e39496225e6d48fb7bb8cd7346c4f311867eafa5 100644
--- a/main/app.c
+++ b/main/app.c
@@ -699,6 +699,7 @@ static int __ast_play_and_record(struct ast_channel *chan, const char *playfile,
 	time_t start, end;
 	struct ast_dsp *sildet = NULL;   /* silence detector dsp */
 	int totalsilence = 0;
+	int dspsilence = 0;
 	int rfmt = 0;
 	struct ast_silence_generator *silgen = NULL;
 	char prependfile[80];
@@ -823,17 +824,13 @@ static int __ast_play_and_record(struct ast_channel *chan, const char *playfile,
 
 				/* Silence Detection */
 				if (maxsilence > 0) {
-					int dspsilence = 0;
+					dspsilence = 0;
 					ast_dsp_silence(sildet, f, &dspsilence);
-					if (dspsilence) {
-						totalsilence = dspsilence;
-					} else {
-						totalsilence = 0;
-					}
+					totalsilence += dspsilence;
 
-					if (totalsilence > maxsilence) {
+					if (dspsilence > maxsilence) {
 						/* Ended happily with silence */
-						ast_verb(3, "Recording automatically stopped after a silence of %d seconds\n", totalsilence/1000);
+						ast_verb(3, "Recording automatically stopped after a silence of %d seconds\n", dspsilence/1000);
 						res = 'S';
 						outmsg = 2;
 						break;
@@ -908,6 +905,12 @@ static int __ast_play_and_record(struct ast_channel *chan, const char *playfile,
 	*duration = others[0] ? ast_tellstream(others[0]) / 8000 : 0;
 
 	if (!prepend) {
+		/* Reduce duration by a total silence amount */
+        	if (totalsilence > 0)
+			*duration -= (totalsilence - 200) / 1000;
+		if (*duration < 0) {
+			*duration = 0;
+		}
 		for (x = 0; x < fmtcnt; x++) {
 			if (!others[x]) {
 				break;
@@ -917,15 +920,9 @@ static int __ast_play_and_record(struct ast_channel *chan, const char *playfile,
 			 * off the recording.  However, if we ended with '#', we don't want
 			 * to trim ANY part of the recording.
 			 */
-			if (res > 0 && totalsilence) {
-				ast_stream_rewind(others[x], totalsilence - 200);
-				/* Reduce duration by a corresponding amount */
-				if (x == 0 && *duration) {
-					*duration -= (totalsilence - 200) / 1000;
-					if (*duration < 0) {
-						*duration = 0;
-					}
-				}
+			if (res > 0 && dspsilence) {
+                                /* rewind only the trailing silence */
+				ast_stream_rewind(others[x], dspsilence - 200);
 			}
 			ast_truncstream(others[x]);
 			ast_closestream(others[x]);
@@ -943,8 +940,8 @@ static int __ast_play_and_record(struct ast_channel *chan, const char *playfile,
 				break;
 			}
 			/*!\note Same logic as above. */
-			if (totalsilence) {
-				ast_stream_rewind(others[x], totalsilence - 200);
+			if (dspsilence) {
+				ast_stream_rewind(others[x], dspsilence - 200);
 			}
 			ast_truncstream(others[x]);
 			/* add the original file too */