Repository: lettre/lettre (language: rust)

Issue:
transport::smtp::Error does not expose error message
I'm currently starting to use lettre (after using it many years ago in one of my first Rust projects) to send email via the AWS SES, and my test code is failing like this:

```rust
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: lettre::transport::smtp::Error { kind: Permanent(Code { severity: PermanentNegativeCompletion, category: MailSystem, detail: Four }) }', service/examples/send.rs:9:45
```

I was able to tease out that `PermanentNegativeCompletion/MailSystem/Four` means a 554 code but this in itself is a fairly obscure way of presenting the error (that is, does not make it easy to connect this API to the on-the-wire API/googling for issues).

Worse, it looks like the `Error` does not preserve any textual content returned by the server, so I don't know which of the 554 variants was actually triggered; and in general, if I had had the error message it would have taken me much less time to figure out the cause of this issue/panic.

**Expected behavior**
Would like `Error` to preserve as much context as possible from the server's response.

**Environment (please complete the following information):**
- Lettre version: 0.10.0-rc.4
- OS: macOS


Discussion / hints:

Fix patch:
diff --git a/src/transport/smtp/client/async_connection.rs b/src/transport/smtp/client/async_connection.rs
index 88c7eb5d3..40b076963 100644
--- a/src/transport/smtp/client/async_connection.rs
+++ b/src/transport/smtp/client/async_connection.rs
@@ -295,7 +295,10 @@ impl AsyncSmtpConnection {
                     return if response.is_positive() {
                         Ok(response)
                     } else {
-                        Err(error::code(response.code()))
+                        Err(error::code(
+                            response.code(),
+                            response.first_line().map(|s| s.to_owned()),
+                        ))
                     }
                 }
                 Err(nom::Err::Failure(e)) => {
diff --git a/src/transport/smtp/client/connection.rs b/src/transport/smtp/client/connection.rs
index 4de1339d5..c1876df93 100644
--- a/src/transport/smtp/client/connection.rs
+++ b/src/transport/smtp/client/connection.rs
@@ -276,7 +276,10 @@ impl SmtpConnection {
                     return if response.is_positive() {
                         Ok(response)
                     } else {
-                        Err(error::code(response.code()))
+                        Err(error::code(
+                            response.code(),
+                            response.first_line().map(|s| s.to_owned()),
+                        ))
                     };
                 }
                 Err(nom::Err::Failure(e)) => {
diff --git a/src/transport/smtp/error.rs b/src/transport/smtp/error.rs
index 675d7c5a0..555cb425f 100644
--- a/src/transport/smtp/error.rs
+++ b/src/transport/smtp/error.rs
@@ -154,10 +154,10 @@ impl StdError for Error {
     }
 }
 
-pub(crate) fn code(c: Code) -> Error {
+pub(crate) fn code(c: Code, s: Option<String>) -> Error {
     match c.severity {
-        Severity::TransientNegativeCompletion => Error::new::<Error>(Kind::Transient(c), None),
-        Severity::PermanentNegativeCompletion => Error::new::<Error>(Kind::Permanent(c), None),
+        Severity::TransientNegativeCompletion => Error::new(Kind::Transient(c), s),
+        Severity::PermanentNegativeCompletion => Error::new(Kind::Permanent(c), s),
         _ => client("Unknown error code"),
     }
 }


Test patch: