diff --git a/src/lib-sieve/sieve-lexer.c b/src/lib-sieve/sieve-lexer.c
index 7fd4f61057565add59ef0dc84a45da0438b9223b..6116e4ccc6bfe555612629f0655987229c1cf29d 100644
--- a/src/lib-sieve/sieve-lexer.c
+++ b/src/lib-sieve/sieve-lexer.c
@@ -565,21 +565,33 @@ static bool sieve_lexer_scan_raw_token(struct sieve_lexer *lexer)
   			
  				/* Parse literal lines */
 				while ( TRUE ) {
+					bool cr_shifted = FALSE;
+
 					/* Remove dot-stuffing or detect end of text */
 					if ( sieve_lexer_curchar(lexer) == '.' ) {
-						bool cr_shifted = FALSE;
 						sieve_lexer_shift(lexer);
   					
 						/* Check for CRLF */
-						if ( sieve_lexer_curchar(lexer) == '\r' ) 
+						if ( sieve_lexer_curchar(lexer) == '\r' ) {
 							sieve_lexer_shift(lexer);
+							cr_shifted = TRUE;
+						}
   				
 						if ( sieve_lexer_curchar(lexer) == '\n' ) {
 							sieve_lexer_shift(lexer);
 							lexer->token_type = STT_STRING;
 							return TRUE;
-						} else if ( cr_shifted ) 
-							str_append_c(str, '\r');  	
+						} else if ( cr_shifted ) {
+							sieve_lexer_error(lexer,
+                                "found CR without subsequent LF in multi-line string literal");
+                            lexer->token_type = STT_ERROR;
+                            return FALSE;
+						}
+
+						/* Handle dot-stuffing */
+						str_append_c(str, '.');
+						if ( sieve_lexer_curchar(lexer) == '.' ) 
+	                        sieve_lexer_shift(lexer);
 					}
   				
 					/* Scan the rest of the line */
diff --git a/src/testsuite/Makefile.am b/src/testsuite/Makefile.am
index a92be128e80da18b5d2b8131dffdc2bfbd9fc129..945b9b7b575b899904ed6632a365567c2c24763d 100644
--- a/src/testsuite/Makefile.am
+++ b/src/testsuite/Makefile.am
@@ -65,6 +65,7 @@ test_cases = \
     tests/testsuite.svtest\
     tests/control-structures.svtest \
 	tests/exists.svtest \
+	tests/lexer.svtest \
 	tests/comparators/core.svtest \
 	tests/match-types/contains.svtest \
 	tests/match-types/matches.svtest \
diff --git a/src/testsuite/tests/lexer.svtest b/src/testsuite/tests/lexer.svtest
new file mode 100644
index 0000000000000000000000000000000000000000..95e668b6dc330aabef658ff3eedf2168f2a2c919
--- /dev/null
+++ b/src/testsuite/tests/lexer.svtest
@@ -0,0 +1,29 @@
+require "vnd.dovecot.testsuite";
+require "variables";
+
+/* Test conformance to RFC 5228 - 2.4.2. Strings */
+
+set "text" text:
+Line 1
+.Line 2
+..Line 3
+.Line 4
+Line 5
+.
+;
+
+set "quoted"
+"Line 1
+.Line 2
+.Line 3
+.Line 4
+Line 5
+";
+
+test "LEXER-string-literal" {
+	if not string :is "${text}" "${quoted}" {
+		test_fail "lexer messed-up dot stuffing";
+	}
+}
+
+