I’ve been working on WeeRust recently which is an IRC client developed using the Rust programming language. A problem recently prevented WeeRust from forwarding the message to me over IMAP because of a temporary network hiccup. Reviewing the code I found an oversight where the send_email() method returns an Option<u32> when instead it should return a Result<(), AppErr> because send_email() can fail. I would like to handle that failure gracefully instead of panic which is what happened the other night crashing my client and disconnecting me from the IRC network. I added the question mark operator to the send_email method here (more details about the question mark here . The question mark operator combined with the signature change will now match either Ok(t) or Err(e), and if the match is an Err, then the function will immediately return Err(e.into())(more on how into() works later). From here there’s a few options; we can create a retry strategy, hold the message in a buffer until it can be viewed later, inform the sender the message can’t be delivered or some combination. Since this application is very much a WIP I decided to just inform the sender the message can’t be forwarded for the time being.

The other change this required is adding a new option to the enum

SmtpError(lettre::transport::smtp::Error)

Next, we need to add a new trait From<T> to the enum. This new From trait does a value-to-value conversion. In our case, it converts:

SmtpError(lettre::transport::smtp::Error)

To:

AppErr::SmtpError(error)

Here is the trait definition looks:

impl From<lettre::transport::smtp::Error> for AppErr {
  fn from(error: lettre::transport::smtp::Error) -> Self {
    AppErr::SmtpError(error)
  }
}

The newly introduced question mark operator can return something that is AppErr::.. even though the original error was a different type. Wrapping an error in a common type while still maintaining the original context information which can be useful for debugging. This is a common pattern for designing error propagation in Rust as described here . The full commit is here .