Repository: lettre/lettre (language: rust)

Issue:
Some subjects with mixed utf8/ascii causes an endless loop
**Describe the bug**
Certain subjects with mixed utf8/ascii (and with a minimum length) 
will cause an endless loop (when the mail later is sent).

**To Reproduce**
```rust
fn main() {

    let problem_subject = "＋仮名 :a;go; ;;;;;s;;;;;;;;;;;;;;;;fffeinmjgggggggggｆっ";

    let mail = lettre::message::Message::builder()
        .to("user@example.com".parse().unwrap())
        .from("user@example".parse().unwrap())
        .subject(problem_subject)
        .body("any".to_string())
        .unwrap();

      let raw = mail.formatted();  //  <-- stuck here
      // ...And .formatted() is called by SmtpTransport::send()  
}
```

**Expected behavior**
I expect it to send the email, or at the very least panic and not get stuck.

**Environment:**
- Lettre version: 0.10.0-rc.3
- OS: tested in windows 10 and in docker/alpine

**Additional context**
I haven't found the exact criteria to cause an endless loop but any shorter string and there will be no problems,
so to me it seems there is a combination of:
**UTF8-chars** followed by **ASCII** followed by **UTF8-chars** **AND** with a minimum length of ~52 characters
For example :
    ❌`＋仮名 :a;go; ;;;;;s;;;;;;;;;;;;;;;;fffeinmjgggggggggｆっ`   endless loop
    ✔ `＋仮名 :a;go; ;;;;;s;;;;;;;;;;;;;;;;fffeinmjggggggggｆっ`   no problem
    ❌`＋仮名 :a;go; ;;;;;s;;;;;;;;;;;;;;;;fffeinmjggggggggｆっg`   endless loop
    ✔`＋仮名 :a;go; ;;;;;s;;;;;;;;;;;;;;;;fffeinmjgggggggggggggggggggg....`   no problem
edit revising my theory:    
     ❌  `aa a00000111111111112222222222333333333344444444ｆｆ`  first space and last utf char seem to important
     ✔  `a aa00000111111111112222222222333333333344444444ｆｆ`   ???
     ❌  `aa a0000011111111111222222222233333333334444444444444あ` 

so my new theory is any string with:
* space somewhere in the chars 2-10, 
* minimum of ~60 bytes
* containing at least one utf8 character anywhere in the string. 

Guessing wildly here but perhaps some parsing for a `Re:` or `Subject:`  causing it?

*edit*

Here is another broken subject to completely ruin your day. Sorry!

`test\u{3000}alphanumericstart alphanumeric ＋仮名 1234567890-^\\`{+*};:]/\\/\\!\"#$%&'()=~|`{+*}<>?_ffhhero 34r9qfiajgh8y30:a;go; ;;;;;;;;;;;;;;;;;;;;;;;;;ffffffffffffeinmjggggggggg\u{3000}ｆっふぁああああああああああああああああああああああああああ最後`

Some subjects with mixed utf8/ascii causes an endless loop
**Describe the bug**
Certain subjects with mixed utf8/ascii (and with a minimum length) 
will cause an endless loop (when the mail later is sent).

**To Reproduce**
```rust
fn main() {

    let problem_subject = "＋仮名 :a;go; ;;;;;s;;;;;;;;;;;;;;;;fffeinmjgggggggggｆっ";

    let mail = lettre::message::Message::builder()
        .to("user@example.com".parse().unwrap())
        .from("user@example".parse().unwrap())
        .subject(problem_subject)
        .body("any".to_string())
        .unwrap();

      let raw = mail.formatted();  //  <-- stuck here
      // ...And .formatted() is called by SmtpTransport::send()  
}
```

**Expected behavior**
I expect it to send the email, or at the very least panic and not get stuck.

**Environment:**
- Lettre version: 0.10.0-rc.3
- OS: tested in windows 10 and in docker/alpine

**Additional context**
I haven't found the exact criteria to cause an endless loop but any shorter string and there will be no problems,
so to me it seems there is a combination of:
**UTF8-chars** followed by **ASCII** followed by **UTF8-chars** **AND** with a minimum length of ~52 characters
For example :
    ❌`＋仮名 :a;go; ;;;;;s;;;;;;;;;;;;;;;;fffeinmjgggggggggｆっ`   endless loop
    ✔ `＋仮名 :a;go; ;;;;;s;;;;;;;;;;;;;;;;fffeinmjggggggggｆっ`   no problem
    ❌`＋仮名 :a;go; ;;;;;s;;;;;;;;;;;;;;;;fffeinmjggggggggｆっg`   endless loop
    ✔`＋仮名 :a;go; ;;;;;s;;;;;;;;;;;;;;;;fffeinmjgggggggggggggggggggg....`   no problem
edit revising my theory:    
     ❌  `aa a00000111111111112222222222333333333344444444ｆｆ`  first space and last utf char seem to important
     ✔  `a aa00000111111111112222222222333333333344444444ｆｆ`   ???
     ❌  `aa a0000011111111111222222222233333333334444444444444あ` 

so my new theory is any string with:
* space somewhere in the chars 2-10, 
* minimum of ~60 bytes
* containing at least one utf8 character anywhere in the string. 

Guessing wildly here but perhaps some parsing for a `Re:` or `Subject:`  causing it?

*edit*

Here is another broken subject to completely ruin your day. Sorry!

`test\u{3000}alphanumericstart alphanumeric ＋仮名 1234567890-^\\`{+*};:]/\\/\\!\"#$%&'()=~|`{+*}<>?_ffhhero 34r9qfiajgh8y30:a;go; ;;;;;;;;;;;;;;;;;;;;;;;;;ffffffffffffeinmjggggggggg\u{3000}ｆっふぁああああああああああああああああああああああああああ最後`



Discussion / hints:

Fix patch:
diff --git a/src/message/header/mod.rs b/src/message/header/mod.rs
index 54e372a6a..bb82be2a8 100644
--- a/src/message/header/mod.rs
+++ b/src/message/header/mod.rs
@@ -411,13 +411,14 @@ impl HeaderValueEncoder {
                 let mut next_word = next_word;
 
                 while !next_word.is_empty() {
-                    if self.remaining_line_len() <= base64_len(1) {
+                    let mut len = available_len_to_max_encode_len(self.remaining_line_len())
+                        .min(next_word.len());
+
+                    if len == 0 {
                         self.flush_encode_buf(f, false)?;
                         self.new_line(f)?;
                     }
 
-                    let mut len = available_len_to_max_encode_len(self.remaining_line_len())
-                        .min(next_word.len());
                     // avoid slicing on a char boundary
                     while !next_word.is_char_boundary(len) {
                         len += 1;
@@ -800,4 +801,21 @@ mod tests {
             )
         );
     }
+
+    #[test]
+    fn issue_653() {
+        let mut headers = Headers::new();
+        headers.insert_raw(
+            HeaderName::new_from_ascii_str("Subject"),
+            "＋仮名 :a;go; ;;;;;s;;;;;;;;;;;;;;;;fffeinmjgggggggggｆっ".to_string(),
+        );
+
+        assert_eq!(
+            headers.to_string(),
+            concat!(
+                "Subject: =?utf-8?b?77yL5Luu5ZCN?= :a;go; \r\n",
+                " =?utf-8?b?Ozs7OztzOzs7Ozs7Ozs7Ozs7Ozs7O2ZmZmVpbm1qZ2dnZ2dnZ2dn772G44Gj?=\r\n"
+            )
+        );
+    }
 }


Test patch: